2010年曾經使用Doxygen生成全中文的chm文檔。由于Doxygen生成的chm目錄文件(index.hhc)本身是使用UTF-8編碼的,而古老的chm編譯器(HTML Help Workshop)對于CHM控制文件(index.hhc、index.hhk、index.hhp),卻只支持ANSI編碼(即本地編碼,如中文系統為GBK),所以最終編譯出來的chm文件,左邊的目錄導航欄全是亂碼。為了解決這個問題,可費了一番工夫,得先使用編碼轉換工具轉換后再用chm編譯器編譯(見:使用doxygen為C/C++程序生成中文文檔)。
今天重新拿起Doxygen,驚喜地發現,它已經支持生成ANSI編碼的chm目錄文件(index.hhc)了,所以能省好多工夫,現在終于可以一步搞定。現在想來,Doxygen早就應該支持這個功能的,做起來也很簡單——當然我沒有詳細去翻查Doxygen是從哪個版本開始支持的,反正Doxygen 1.8.0是支持的,想必之后的版本都支持。
下載和安裝 Doxygen
到 Doxygen 官網 下載最新的Doxygen安裝程序,然后安裝。這個軟件包包括了一個GUI界面的前端工具,可以幫助我們方便創建Doxygen配置文件和生成目標文檔。
下面以 Doxygen 1.8.0 為例進行講解。
下載和安裝 chm 編譯器
我們使用微軟古老的 HTML Help Workshop 1.3,這個軟件N久沒更新了。
下載地址: 微軟官網
下載后根據提示安裝。
項目一般設置
首先在“Wizard”標簽的Project項進行如下設置:
-
項目名稱:將在最新的文檔首頁中顯示
-
源碼列表:選擇要生成文檔的源代碼或目錄,可以有多個文件或目錄形成一個列表。建議使用相對路徑,相對于當前目錄(也即當前配置文件所在的目錄)
-
遞歸掃描:如果需要對整個源碼目錄下的所有子目錄及文件生成文檔,請勾選本項
-
輸出目錄:設置最終生成的幫助文檔的存儲路徑,建議使用相對路徑
下一步,Mode項,根據需要設置文檔生成模式。
下一步,Output項,設置輸出格式,勾選HTML和“prepare for compressed HTML(.chm)”
然后切換到“Expert”標簽的“HTML”項,設置HTML和CHM相關的選項:
-
GENERATE_HTMLHELP:確保已經勾選了
-
CHM_FILE:最終生成的.chm的文件名,如“HkcProjectHelp.chm”。默認為“index.chm”。可以使用路徑,也可以使用相對路徑,相對于上面設置的輸出目錄的html目錄(建設使用上一級目錄,如“..\MyDoc.chm”)
-
HHC_LOCATION:chm 編譯器(hhc.exe)的全路徑。請指到
HTML Help Workshop 的安裝目錄的 hhc.exe 程序
-
CHM_INDEX_ENCODING:chm索引文件編碼,下面會講到,這里填“GBK”
編碼設置
編碼設置很重要,如果設置不當,生成的文檔會出現亂碼。因為 Doxygen 汲及的東西多,有好幾項編碼設置,所以需要認真對待,根據項目的實情情況設置。
所有高級設置(包括編碼設置)都在“Expert”標簽,重要的設置項如下:
-
Project/DOXYFILE_ENCODING:當前 Doxygen 配置文件本身的字符編碼,默認為UTF-8,一般不需要修改
-
Project/OUTPUT_LANGUAGE:輸出語言。這里是指Doxygen自己生成的導航、提示、幫助等文本的文字采用的語言。我們希望幫助文檔是全中文的,所以選擇Chinese
-
Input/INPUT_ENCODING:輸入文件的編碼。這里是指我們的源代碼文件本身的編碼。在Windows平臺一般是系統編碼(GBK),而Linux平臺一般是UTF-8。請用文本編輯器查看源文件的編碼。這里如果設置的不一致,源碼文件的注釋中所有非ASCII字符將在生成的文檔中變成亂碼。
-
HTMP/CHM_INDEX_ENCODING:這里設置Doxygen生成的CHM索引文件的編碼,以前是不能設置的,默認為UTF-8,而微軟的編譯器不能識別UTF-8編碼的索引文件,所以最終造成左邊目錄導航欄亂碼。我們設置它為GBK,這樣Doxygen將為我們生成GBK編碼的索引文件(.hhc、.hhk、.hhp)
生成CHM文檔
設置好了后,點擊“Run”→“Run doxygen”生成最終的.chm文檔,如果設置正確,打開后是全中文的了。
先介紹個比較簡單的程序,windows下讀內存:

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

const char FileMaping[255] = "FileMaping";
typedef struct file_map_parameter_t


{
int i_id;
int j_id;
char c_id;
}file_map_parameter_t;

typedef file_map_parameter_t FileMap_t[100];
file_map_parameter_t * m_addr;

bool ReadFileMapping()


{
size_t len = sizeof(FileMaping);
wchar_t* wstr_name = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
HANDLE m_handle = ::OpenFileMapping(FILE_MAP_ALL_ACCESS,false,wstr_name);
if (NULL == m_handle)

{
m_handle = ::CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,
sizeof(FileMap_t),wstr_name);
if( NULL == m_handle)

{
cout<<"共享文件生成失敗!"<<endl;
return false;
}
else

{
cout<<"共享文件生成成功!"<<endl;
}

}
m_addr = (file_map_parameter_t*)::MapViewOfFile(m_handle,FILE_MAP_WRITE,0,0,sizeof(FileMap_t));

for (int i = 0;i<20;i++)

{
file_map_parameter_t * m_addrtmp;
m_addrtmp = m_addr + i;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])


{
ReadFileMapping();
return 0;
}

寫共享內存:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
const char FileMaping[255] = "FileMaping";
typedef struct file_map_parameter_t
{
int i_id;
int j_id;
char c_id;
}file_map_parameter_t;
typedef file_map_parameter_t FileMap_t[100];
file_map_parameter_t * m_addr;
bool WriteFileMapping()
{
size_t len = sizeof(FileMaping);
wchar_t* wstr_name = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
HANDLE m_handle = ::OpenFileMapping(FILE_MAP_ALL_ACCESS,false,wstr_name);
if (NULL == m_handle)
{
m_handle = ::CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,
sizeof(FileMap_t),wstr_name);
if( NULL == m_handle)
{
cout<<"共享文件生成失敗!"<<endl;
return false;
}
else
{
cout<<"共享文件生成成功!"<<endl;
}
}
m_addr = (file_map_parameter_t*)::MapViewOfFile(m_handle,FILE_MAP_WRITE,0,0,sizeof(FileMap_t));
for (int i = 0;i<20;i++)
{
(m_addr + i)->c_id = 'i';
(m_addr + i)->i_id = i;
(m_addr + i)->j_id = 2*i;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
WriteFileMapping();
return 0;
}
這里有一個問題沒有解決:
對共享內存的大小問題,比如說上面寫的程序是已知共享內存的大小,比如說有20個struct,但是如果
這個大小不是固定的比如類似于一個vector的話該怎么操作呢?
利用boost::interprocess請看
http://blog.csdn.net/great3779/article/details/7226388
先上代碼:

#include "stdafx.h"
#include<iostream>
#include "luabind\luabind.hpp"

extern "C"


{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

using namespace std;

bool LoadScript(lua_State *L,const string& fname)


{
if (luaL_dofile(L,fname.c_str()))

{
cerr<<lua_tostring(L,-1)<<endl;
return false;
}
return true;
}

void testFunc(int k)


{
cout<<"hello there, i am a cpp fun"<<endl;
cout<<"input num:="<<k<<endl;
}


class NumberPrinter
{
public:
NumberPrinter(int number) :

m_number(number)
{}


void print()
{
cout << m_number << endl;
}

private:
int m_number;
};


int _tmain(int argc, _TCHAR* argv[])


{
using namespace luabind;
lua_State* L = luaL_newstate();
module(L, "cppapi")
[
def("testFunc", (void(*)(int))testFunc)
];

// 使用LuaBind導出NumberPrinter類
luaopen_base(L);
luabind::open(L);

luabind::module(L)
[
luabind::class_<NumberPrinter>("NumberPrinter")
.def(luabind::constructor<int>())
.def("print", &NumberPrinter::print)
];
luaL_openlibs(L);
LoadScript(L,"test.lua");

try
{
int add_ret = luabind::call_function<int>(L,"add",10,4);
int call_global = luabind::object_cast<int>(luabind::globals(L)["nGlobal"]);
string strGlobal = luabind::object_cast<string>(luabind::globals(L)["strGlobal"]) ;
luabind::object lua_object = luabind::globals(L)["t"];
//--2種辦法load table
string strName = luabind::object_cast<string>(lua_object["name"]);
int iAge = luabind::object_cast<int>(lua_object["age"]);
string strElse = luabind::object_cast<string>(lua_object["desc"]);
}
catch(luabind::error& e)

{
cout<<e.what()<<endl;
printf("AI throw error: err_msg[%s]", lua_tostring(L, -1));
return false;
}
lua_close(L);
return 0;
}其中test.lua的代碼如下:
Print2000 = NumberPrinter(2000)
Print2000:print()
nGlobal = 10 --一個全局的整形變量
strGlobal = "hello i am in lua" --一個全局的字符串變量
--一個返回值為int類型的函數
function add(a, b)
return a+b
end
--一個返回值為string類型的函數
function strEcho(a)
print(a)
return 'haha i h
ave print your input param'
end
cppapi.testFunc(10) --調用c++暴露的一個測試函數
t={name='ettan', age=23, desc='正值花季年齡'}
運行結果為:

這上面luabind調用c++函數的實例:調用testFunc函數;也有c++調用lua的代碼,具體的見代碼。
此代碼在我的vs2010上面調試通過,前提是必須配好環境如:添加依賴庫luabind.debug.lib;lua.debug.lib
添加依賴庫路徑。
特別注意:
首先Lua是“動態編譯的腳本語言”,而loadfile只是把源文件加載到內存中,還少了“編譯”這一步,可以用“luaL_dofile(L,"test.lua");”來替換,它既加載又編譯。替換之后執行應該就沒有問題了。
但是還沒完,luaL_dofile 實際上是個宏:
- #define luaL_dofile(L, fn) \
- (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
LUA_MULTRET也是宏定義,值為-1,表示函數有多個返回值(Lua規則,pil 24.2--堆棧)。
擴展開來就是以下兩句:
- luaL_loadfile(L, fn);
- lua_pcall(L, 0, LUA_MULTRET, 0);
pcall以上述參數執行的時候,會把加載到內存中的源程序編譯成可以用于執行的2進制代碼,并將全局變量壓棧(在Lua中,函數也是變量,pil 2.5 -- Functions,畢竟函數名和函數體是不同的2個東西)。就跟PE文件格式里的Section一樣(PE文件就是Windows3.1之后的.exe/.dll文件)。當然如果你不知道什么PE文件也沒關系--我只是打個比方--就當成VS2005編譯代碼時生成的.obj文件。
雖然實際使用中99%的情況都是直接使用dofile,但是我想將該問題提出來說可以更加直觀的理解“動態編譯”。
參照:
代碼和文字大部分出自 1. http://blog.csdn.net/caoyanting007/article/details/5709820
2. http://mobile.51cto.com/iphone-285654.htm
在最近做的一個項目中需要用到檢測進程狀態的功能,在網上兜了半圈,普遍介紹的方法有三種:
1. 是利用GetExitCodeProcess(pi.hProcess,&dwExitCode);通過看dwExitCode返回值是不是
STILL_ACTIVE,依然活動,說明存在;
2 .waitforsingleobject,通過超時來判斷,具體的實現方法可以去網上查,
3. openprocess,通過返回值來判斷,如果返回值為NULL則表示進程已經打開,否則沒有打開。
上面3個方法別人都說行,也有人說有局限性,就拿openprocess來說吧,自己在測試是發現線程關掉了但是返回值還是NULL,郁悶啊~~,沒辦法只能用最土的辦法來解決這個問題,
4. load系統的進程表,看進程id是不是匹配,匹配則表示正在運行,否則就已經掛了,代碼如下:
#include <Tlhelp32.h>
//如果有運行,返回進程的true,沒運行返回false
bool ProcessExist(DWORD process_id)
{
PROCESSENTRY32 pe;
DWORD id = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize = sizeof(PROCESSENTRY32);
if( !Process32First(hSnapshot,&pe) )
{
CloseHandle(hSnapshot);
return false;
}
while(1)
{
pe.dwSize = sizeof(PROCESSENTRY32);
if( Process32Next(hSnapshot,&pe)==FALSE )
{
CloseHandle(hSnapshot);
return false;
}
if(process_id == pe.th32ProcessID)
{
CloseHandle(hSnapshot);
return true;
}
}
}
先直接上方法
1. 準備好boost編譯文件;
2.(我放在D:/cpp目錄下)解壓到當前文件夾
3.打開VS2010->VS TOOLS->VS命令提示
4.CD D:/cpp/boost_1_46_1
5.輸入bootstrap,便生成bjam.exe文件
6.輸入bjam toolset=msvc-10.0 variant=debug,release threading=multi link=static,便生成boost庫(20多分鐘,時間已經算很短了,之前都是1,2個小時應該是跟這個參數有關,編譯完成后為1G多一點,之前都是3.7G左右)
7.修改VS2010的參數 在項目的組合顯示那找到屬性頁,打開屬性頁,選擇配置屬性,選擇VC++目錄,設置includepath和libpath,
如我的為D:/cpp/boost_1_46_1;$(IncludePath)
D:/cpp/boost_1_46_1/stage/lib;$(LibraryPath)
圖解參照
http://blog.csdn.net/respawn/article/details/7588396,這個弄的很清楚。