最近寫 Android,一般 Java 層可以透過 JNI 呼叫 C/C++ 撰寫的 .so 檔,但是要從 C/C++ 呼叫回 Java 層呢!? 一般需要 JNIEnv 這個特殊的變數,才可以透過它來呼叫到 Java Library。
不過今天這邊要介紹的是另外一個方法 - 透過 SWIG 的 directors 的 feature
SWIG 可以將 C++ 的 class 包裝成一個 Java layer 的 class ,而 Java layer 可以去繼承 Java wrap C++ 的 class,然後 override 它的 virtual function 後,C/C++ layer 呼叫到這個 virtual function 時,就會被轉 call 到 Java layer了。
27 12月 2013
20 12月 2013
[emomeDDSMS] 下載emome上的備份簡訊 更新0.74
emome更新
好久沒更新了,最近要備份才發現網頁更新了 XD,就順手改了一下
還得要抓到舊版的 Firefox 3.6 才行,還好 chickenfoot 的連結還在...
下載連結(按右鍵另存新檔):emomeDDSMS 0.74 (2013/12/20)
使用說明,請參考前一篇文章。
下載連結(按右鍵另存新檔):emomeDDSMS 0.74 (2013/12/20)
使用說明,請參考前一篇文章。
11 12月 2013
[JNI] 在C/C++中透過 SWIG 取得 JNIEnv or JavaVM
在 C/C++ layer 裡,想要 call Java layer 的 function 的話,適必需要 JNIEnv or JavaVM 這兩個 instance pointer,而透過 SWIG 包裝起來的 C/C++ layer 是不能直接接觸到 JNI layer,必須要一些手法才行。
[C/C++] 在 Windows 上 Build static libCURL library
libcurl 是個跨平台的 library ,支援非常多的 protocol,重點還是 open source!
以下就是簡單的 build 出一個 libcurl 的 static library 教學
build 完後,可以在 {libcurl extract dir}\builds 找到 lib 還有 header 檔
其他參數說明
加上放有 build 出的 .lib 的目錄
在 Project Property | Linker | Input | Additional Dependencies
加上 libcurl_a.lib or libcurl_a_debug.lib
在 Project Property | C/C++ | Preprocessor
加上 CURL_STATICLIB 這個 macro 才行
否則會出現類似這樣的錯誤訊息:
以下就是簡單的 build 出一個 libcurl 的 static library 教學
1. 首先 download libcurl 的 source code 壓縮檔
libCURL download page2. 在 command line 準備好 VC 的 compile 環境
"{VC Install Path}\VC\vcvarsall.bat" x86設置完環境後,才能執行 namke
3. 開始 build libcurl
cd {libcurl extract dir}\winbuild nmake /f Makefile.vc mode=static DEBUG=yes MAXHINE=x86mode = static 也可以是 dll ,只是我們目標是 static library
build 完後,可以在 {libcurl extract dir}\builds 找到 lib 還有 header 檔
其他參數說明
- VC=<6,7,8,9,10>
- VC版本(不一定要填)
- WITH_SSL=<dll or static>
- 使用OpenSSL詳細參閱,會有 License 問題
- ENABLE_WINSSL=<yes or no>
- Enable native 的 Windows SSL 功能
- 記得,如果要 enable 的話,ENABLE_SSPI一定也要 enable !
- GEN_PDB=<yes or no>
- 產生 .pdb 檔
- DEBUG=<yes or no>
- Debug or Release mode
- MACHINE=<x86 or x64>
- Target architecture
- RTLIBCFG
- 不指定就是 default,compile 參數會加上 /MD or /MDd (Multi-threaded)
- =static,compile 參數會加上 /MT or /MTd (Multi-threaded DLL)
4. VC project setting 設置
在 Project Property | Linker | General | Additional Library Directories加上放有 build 出的 .lib 的目錄
在 Project Property | Linker | Input | Additional Dependencies
加上 libcurl_a.lib or libcurl_a_debug.lib
在 Project Property | C/C++ | Preprocessor
加上 CURL_STATICLIB 這個 macro 才行
否則會出現類似這樣的錯誤訊息:
1>A.obj : error LNK2019: unresolved external symbol __imp__curl_global_init referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_append referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_free_all referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_strerror referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_init referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_setopt referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_perform referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_cleanup referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
12 11月 2013
[Linux/Android] Export API for SharedLibrary (.so)
當開發一個 SharedLibrary (.so) 時,不想 Export 太多 API 出去(可能涉及商業機密或是單純的爽字),Windows or Linux 都有做法可以做到,這邊只說明一下 Linux / Android 的做法。
用 nm 觀察 .so 的 Symbol Table
nm -gC MyLib.so
- -g : 只列出 external symbol
- -C : 將 C++ 的 symbol 轉換成易讀的版本
30 10月 2013
[Android] 在 C Level 用 dlopen 使用 第三方的 Shared Library (.so)
在 Android 裡,撰寫 JNI C Level 的 code ,不管是想要 load 自己寫的獨立 shared library module (.so),或是想要把第三方的 shared library 拿來用,都必須要多做一些步驟才能達成。
08 10月 2013
[Android] NDK Debug 與 breakpoint 失效的解決之道
在 Android 開發環境裡,新版的 NDK (目前為 r9 )提供的 GDB Debug C//C++環境其實已經算是很友善的了。不像以前需要下一堆的 command line 才行。
目前我的開發環境:
簡單說一下 Debug NDK 的步驟
填入正確的 NDK 下載路徑
取消 Use default build command的選項
輸入 ndk-build NDK_BUILD=1
註:Application.mk or Android.mk 都無需修改,新版的 ADT/NDK 都已經 handle 好其他的設定了
所以如果 Debug As "Android Application"的話,就是 Debug Java level
如果 Debug As "Android Native Application"的話,就是 Debug C/C++ level
目前我的開發環境:
- ADT - adt-bundle-windows-x86_64-20130729
- NDK - android-ndk-r9
簡單說一下 Debug NDK 的步驟
1. Eclipse Preferences
設定 Eclipse Preference | Android | NDK | NDK Location填入正確的 NDK 下載路徑
2. 設定 Project property NDK_DEBUG=1
Project Property | C/C++ Builder | Builder Settings取消 Use default build command的選項
輸入 ndk-build NDK_BUILD=1
註:Application.mk or Android.mk 都無需修改,新版的 ADT/NDK 都已經 handle 好其他的設定了
3. 設好中斷點
在 Eclipse 裡的 C/C++ code,設好中斷點,等著上鉤4. Debug As "Android Native Application"
由於目前 ADT 在 Debug 時,同一時間只能選擇 Debug Java or C/C++所以如果 Debug As "Android Application"的話,就是 Debug Java level
如果 Debug As "Android Native Application"的話,就是 Debug C/C++ level
* 問題 *
Debug 時設中斷點,可能會出現類似這樣的Error- No symbol table is loaded. Use the "file" command.
14 8月 2013
[Win32] 在C/C++中偵測精準的程式時間(Performance Time)
在Windows底下,要偵測精準的Perfromance Time,可以透過QueryPerformanceFrequency() & QueryPerformanceCounter() 來取得。
由於取得的時間存在LARGE_INTEGER的structure,要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class,讓這個AutoQueryPerformance的instance life-time結束後,自行dump出所花費的時間。
Reference
由於取得的時間存在LARGE_INTEGER的structure,要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class,讓這個AutoQueryPerformance的instance life-time結束後,自行dump出所花費的時間。
AutoQueryPerformance
#include "windows.h" // Auto dump the life-time of AutoQueryPerformance // Ex: // { // AutoQueryPerformance autoQuery("Test", true); // ... // } // it will dump message when @autoQuery destroy class AutoQueryPerformance { public: AutoQueryPerformance(const char* info, INT loop_count=1, BOOL autoDump=TRUE) : m_count_time(0), m_loop_count(loop_count), m_auto(autoDump) { m_info = info; ::ZeroMemory(&m_cpu_freq, sizeof(LARGE_INTEGER)); ::QueryPerformanceFrequency(&m_cpu_freq); if( autoDump ) begin(); } ~AutoQueryPerformance() { pause(); if( autoDump ) printf("[AutoQueryPerformance][%s] spend time=%.4f", m_info.c_str(), getTime()); } inline void begin() { ::ZeroMemory(&m_start_clock, sizeof(LARGE_INTEGER));; ::QueryPerformanceCounter(&m_start_clock); } inline void pause() { ::ZeroMemory(&m_cur_clock, sizeof(LARGE_INTEGER)); ::QueryPerformanceCounter(&m_cur_clock); m_count_time += m_cur_clock.QuadPart-m_start_clock.QuadPart; } inline void stop() { pause(); m_count_time = 0; } inline float getTime() { return (m_count_time/(float)m_cpu_freq.QuadPart) / m_loop_count; } private: LARGE_INTEGER m_cpu_freq; LARGE_INTEGER m_start_clock; LARGE_INTEGER m_cur_clock; LONGLONG m_count_time; INT m_loop_count;//for for-loop to calculate correct average time std::string m_info; BOOL m_auto; }; #define AUTO_QUERY_PERFORMANCE(x) AutoQueryPerformance __at_qp = AutoQueryPerformance(x);
使用範例
void TestingTotalTime(int loop_count) { AutoQueryPerformance ap("TestingTotalTime"); int sum = 0; for(int i=0 ; i<loop_count; i++) sum += i; } void TestingSingleTime(int loop_count) { AutoQueryPerformance ap("TestingSingleTime", loop_count); for(int i=0 ; i<loop_count; i++) //HeavyFunction call here; }
Reference
- MSDN - QueryPerformanceFrequency
- MSDN - QueryPerformanceCounter
12 8月 2013
[Win32/COM] Use COM DLL without registered
依照Windows COM元件的使用方法,應該要將COM DLL註冊後,即可在程式中,以CoCreateInstance()帶入CLSID、IID就可以將該DLL自動load起來,創建該class的instance了。
但是在開發時,實際上總是沒這麼美好,註冊DLL其實是很麻煩的,新舊相容性,開發中的版本等等的問題,而走manifest其實可以避開註冊這條路,但是今天我需要寫一個COM module讓別人使用,而這個COM module在AP裡是走manifest的,所以不會被註冊,連帶的module會用到其他的Library也不走註冊這條路,而因為一些其他的原因,也不能將此Library寫入manifest裡,只能尋求其他途徑了。
由於COM的DLL都會link到一些基本的COM Library,所以是有一些export的API可以繞過註冊來create COM instance的,直接參考以下的Sample Code吧。
Reference:
但是在開發時,實際上總是沒這麼美好,註冊DLL其實是很麻煩的,新舊相容性,開發中的版本等等的問題,而走manifest其實可以避開註冊這條路,但是今天我需要寫一個COM module讓別人使用,而這個COM module在AP裡是走manifest的,所以不會被註冊,連帶的module會用到其他的Library也不走註冊這條路,而因為一些其他的原因,也不能將此Library寫入manifest裡,只能尋求其他途徑了。
由於COM的DLL都會link到一些基本的COM Library,所以是有一些export的API可以繞過註冊來create COM instance的,直接參考以下的Sample Code吧。
// {599D2F5F-BA8D-4009-941C-A5393EBD5C58} DEFINE_GUID(CLSID_MyCOM, 0x599d2f5f, 0xba8d, 0x4009, 0x94, 0x1c, 0xa5, 0x39, 0x3e, 0xbd, 0x5c, 0x58); // {4C452CB2-469C-4236-AE5C-F48A28EC0870} DEFINE_GUID(IID_IMyCOM, 0x4c452cb2, 0x469c, 0x4236, 0xae, 0x5c, 0xf4, 0x8a, 0x28, 0xec, 0x8, 0x70); HRESULT CreateInstance(IMyCOM** pMyCom) { HMODULE hDll = LoadLibrary("MY_COM.dll");//Need refine by your self if(hDll) { ////////////////////////////////////////////////////////////////////////// // Initial COM instance without register // Try to load COM DLL directly, and call DllGetClassObject to get IID_IClassFactory // And Create COM instance by IID_IClassFactory // ----------------------------------------------------------------------- // HRESULT hr = CoCreateInstance(CLSID_MyCOM, // NULL, // CLSCTX_INPROC_SERVER, // IID_IMyCOM, // (PVOID*)&pMyCom); ////////////////////////////////////////////////////////////////////////// CComPtr<IClassFactory> spFactory; // Get address of DllGetClassObject exported method PDLLGETCLSOBJ pDllGetCLSObj = (PDLLGETCLSOBJ)GetProcAddress(hDll, "DllGetClassObject"); // Call DllGetClassObject and get the proper IClassFactory interface HRESULT hr = pDllGetCLSObj(CLSID_MyCOM, IID_IClassFactory, reinterpret_cast<PVOID*>(&spFactory)); if( FAILED(hr) ) { printf(__FUNCTION__" [Err] Can't get spFactory hr=%X", hr); return E_FAIL; } // Create an instance of IMyCOM hr = spFactory->CreateInstance(NULL, IID_IMyCOM, (PVOID*)pMyCom); if( FAILED(hr) ) { printf(__FUNCTION__" [Err] Init IMyCOM Fail! hr=%X", hr); return E_FAIL; } } else { return E_FAIL; } return S_OK; }
Reference:
- StackOverflow - Windows/C++: how to use a COM dll which is not registered
[Python] 使用objgraph找出memory leak(circular reference)
在Python的世界裡,所有的東西都是Object,而控制Object的life cycle靠的就是reference的機制,一個簡單的assignement (=等號),或是function call就會讓Object的reference count自動加1。
而當Object的reference count減至0的時候,Python的GC會找時間把這些Object清除掉。
對Python而言,memory leak產生的可能性有兩種
而當Object的reference count減至0的時候,Python的GC會找時間把這些Object清除掉。
對Python而言,memory leak產生的可能性有兩種
- Circular reference
- Referece在global的變數或是module上
18 7月 2013
[Jython] Use JNA Read/Write Windows Registry
最近用Sikuli開發,Run Script時需要讀寫Windows的Registry,由於Sikuli script是用Jython的,而Jython裡並不像Python支援Read/Write Windows Registry,所以必須用一些其他的Library才行
而其中一個方法就是用JNA
下載最新的JNA與JNA-Platform
放到要執行的Script旁,或是放到Jython的目錄裡
以下的範例,將jna-3.5.1.jar與jna-platform-3.5.1.jar放到Sample.py旁,以Jython執行
Sample.py
Reference
而其中一個方法就是用JNA
下載最新的JNA與JNA-Platform
放到要執行的Script旁,或是放到Jython的目錄裡
以下的範例,將jna-3.5.1.jar與jna-platform-3.5.1.jar放到Sample.py旁,以Jython執行
Sample.py
import os import sys folder = os.path.dirname(os.path.abspath(__file__)) # load JavaLib jna/platform sys.path.append(os.path.join(folder, 'jna-3.5.1.jar')) sys.path.append(os.path.join(folder, 'jna-platform-3.5.1.jar')) # Read from com.sun.jna.platform.win32 import Advapi32Util, WinReg path = Advapi32Util.registryGetStringValue( \ WinReg.HKEY_LOCAL_MACHINE, r'Software\CyberLink\ColorDirector2', 'InstallPath' ) print path.encode(sys.getfilesystemencoding())
Reference
17 7月 2013
[Python] Windows底下 使用SWIG呼叫C/C++的function
使用Python的script language的特性,開發起來實在是又快又舒服,但是Python有個致命的缺點就是GIL,在Multi-Thread的機制下,有了這個GIL的限制,感覺Multi-Thread就被俺掉一半了。照理來說heavy的blocking code應該要寫在另一條thread,並且放掉GIL,讓其他的thread有時間去做事才對。透過Python轉call進C/C++的function後,才有機會讓heavy的function放掉Python的GIL。
不過,本篇的重點在於介紹如果讓Python呼叫C/C++ level的function,有機會的話,再介紹一下GIL好了。目前其實有很多Tool提供這樣的功能,包括SWIG、Boost.Python、Robin…等等,這邊就介紹一下SWIG的用法。
不過,本篇的重點在於介紹如果讓Python呼叫C/C++ level的function,有機會的話,再介紹一下GIL好了。目前其實有很多Tool提供這樣的功能,包括SWIG、Boost.Python、Robin…等等,這邊就介紹一下SWIG的用法。
25 6月 2013
[PHP] Debug PHP by Eclipse with PDT PlugIn
強大的Eclipse開發社群,提供了PHP的debug功能 - PHP Development Tool (PDT) PlugIn,可以執行並下中斷點,對PHP開發者而言著實是一大福音!
PDT套件可以視為是debug的client端,而server端的話,就需要在PHP安裝extension才行,目前PDT支援的包括(1)Zend Debugger (2)XDebug,以下就介紹PDT以Zend Debugger的方式進行debug ...
PDT套件可以視為是debug的client端,而server端的話,就需要在PHP安裝extension才行,目前PDT支援的包括(1)Zend Debugger (2)XDebug,以下就介紹PDT以Zend Debugger的方式進行debug ...
06 6月 2013
[Sikuli] Compile Sikuli-IDE source code in Eclipse
Sikuli是新堀起的Programming Language,以圖象化的方式來coding真的是一大圖破創新的想法。重點是...還是台灣人做的呢!Sikuli是Open Source的,所以有不少人為這個Project供獻一己之力,最近公司的Project用它來做AutoTest,整個很給力,決定來compile它的source code來玩看看,雖然說很久沒寫Java了.... XD
Sikuli的Project切成兩部分,一個是整個核心的Sikuli-API是以Java、C++為主,另一個是開發平台的Sikuli-IDE是純Java的Project,由於整個核心API切出來成一個單獨的Project,所以如果想自己寫一個Java的程式直接使用Sikuli-API是可行的!詳見:How to use Sikuli Script in your Java Program?
也由於Sikuli API模組化的關係,目前Sikuli Script語法是Python,以後可能還會陸續支援其他語言吧。
Sikuli的Project切成兩部分,一個是整個核心的Sikuli-API是以Java、C++為主,另一個是開發平台的Sikuli-IDE是純Java的Project,由於整個核心API切出來成一個單獨的Project,所以如果想自己寫一個Java的程式直接使用Sikuli-API是可行的!詳見:How to use Sikuli Script in your Java Program?
也由於Sikuli API模組化的關係,目前Sikuli Script語法是Python,以後可能還會陸續支援其他語言吧。
25 5月 2013
[C/C++] 研究long long * float overflow 可能導致的誤差
最近看bug看到一個奇怪的現象,在64bit的AP執行時,long long * float會有誤差出現,但是32bit的AP卻沒有這樣子的問題出現,直覺上不是應該32bit的AP比較會有問題嗎!?
先來看一下 long long 跟 float ,long long的size是8個byte,float的size是4個byte
long long * float,compiler會將結果存到float的temp變數裡,此時誤差就可能會出現了,但是這個誤差是「有條件」地出現,並不是任何long long的數字乘上float都會產生誤差的
以一個簡單的程式來驗證是否會產生誤差
先來看一下 long long 跟 float ,long long的size是8個byte,float的size是4個byte
long long * float,compiler會將結果存到float的temp變數裡,此時誤差就可能會出現了,但是這個誤差是「有條件」地出現,並不是任何long long的數字乘上float都會產生誤差的
以一個簡單的程式來驗證是否會產生誤差
bool check_longlong(long long v1) { float f = 1.0f; long long v2 = long long( v1 * f ); printf("ori value=%lld, new value=%lld, ori==new=%d", v1, v2, v1==v2); return v1==v2; } int _tmain(int argc, _TCHAR* argv[]) { check_longlong(0xF0000000000);//true - OK check_longlong(0x0FFFFFFFFFF);//false - Error! check_longlong(0x0FFFFFF);//true - OK check_longlong(0x1FFFFFF);//false - Error! return 0; }
24 5月 2013
[C/C++] 使用STL時,混用Debug & Release Mode的DLL or LIB可能會造成 Crash!
當你的Release mode的EXE,使用Debug mode的DLL,中間如果有操作(new/delete)STL的container,很容易讓AP crash,包括下列的error ...
- Debug Assertion Failed
- _BLOCK_TYPE_IS_VALID
- _CrtIsValidHeapPointer
[Python] 為Python2.5 unittest 加上setUpClass & tearDownClass 的功能
最近使用 Sikuli 替Project作AutoTest的功能,以Python的unittest為架構下去撰寫,發現有些綁手綁腳的地方,因為Sikuli是使用Jython 2.5,連帶的unittest也止於Python 2.5的版本。由於測試的項目眾多,需要撰寫多個TestCase,所以setUpClass與tearDownClass更顯得重要,可以為每個TestCase做pre-process與post-process。偏偏setUpClass與tearDownClass是在Python 2.7後才支援的,所以想在Sikuli裡套用的話,必須自己加一些Code才行了。
23 5月 2013
[C/C++] 取得LIB目前的DLL module path
如果寫了一個LIB or Cpp檔,讓多個DLL module include使用,該如果拿到目前DLL的module path?
GetModuleFileName() 參數hModule傳NULL的話,只能知道執行檔exe的路徑
要想知道自己在哪個DLL module的話,必須埋一些code才行
Reference :
GetModuleFileName() 參數hModule傳NULL的話,只能知道執行檔exe的路徑
要想知道自己在哪個DLL module的話,必須埋一些code才行
EXTERN_C IMAGE_DOS_HEADER __ImageBase //... WCHAR dll_path[MAX_PATH] = {0}; GetModuleFileNameW((HINSTANCE)&__ImageBase, dll_path, _MAX_PATH);
Reference :
- StackOverflow - Get Dll path at runtime
- MSDN - GetModuleFileName()
22 3月 2013
[C/C++] General pointer type for support x86 & x64
一個pointer的size在x86跟x64的環境裡是不一樣大的
- x86's pointer size = 4 bytes
- x64's pointer size = 8 bytes
如果你在程式中用int or long去儲存一個pointer的話,可能在compile成x86可以work,但是compile成x64執行的話,可能就會exception了
所以建議是用標準的 uintptr_t / intptr_t 去儲存pointer,uintptr_t在copmpile成x86時的size是4 bytes,x64是8 bytes,它在C++11時才被列入標準,但在大部分的C++03的compiler已經支援了
include header : <cstdint>
Reference :
10 3月 2013
[wxWidgets] function 傳入wxString的不定參數
在C/C++裡有不定參數的功能,讓一個function可以傳入不固定數目的參數,在function裡,透過va_list, va_arg() 把參數一個個抓出來。
在wxWidgets裡,擁有特有的字串類別wxString,用法跟std::string, std::wstring稍稍不同(多了很多API)。
std::string/std::wstring可以透過c_str()取得的內部字串buffer (char*/wchar_t*)
wxString也可以透過c_str()取得內部字串的buffer,型別是wxChar
wxChar是wxWidgets定義的,會根據compile定義的wxUSE_UNICODE(是否為unicode的build)分別對應到unicode : wchar_t, ansi : char
由於wxString是wxWidgets包裝起來的class,若將它傳進function當不定參數之一,va_arg()將無法取得wxString正確的字串內容,所以如果要將wxString的字串傳入不定參數的function中,需以c_str()傳入wxChar*字串的pointer,才能在function中取得字串的內容。
在wxWidgets裡,擁有特有的字串類別wxString,用法跟std::string, std::wstring稍稍不同(多了很多API)。
std::string/std::wstring可以透過c_str()取得的內部字串buffer (char*/wchar_t*)
wxString也可以透過c_str()取得內部字串的buffer,型別是wxChar
wxChar是wxWidgets定義的,會根據compile定義的wxUSE_UNICODE(是否為unicode的build)分別對應到unicode : wchar_t, ansi : char
由於wxString是wxWidgets包裝起來的class,若將它傳進function當不定參數之一,va_arg()將無法取得wxString正確的字串內容,所以如果要將wxString的字串傳入不定參數的function中,需以c_str()傳入wxChar*字串的pointer,才能在function中取得字串的內容。
// the parameter must be wxChar* // -> please convert wxString by c_str() before push it // _T("") would be convert to wxChar* // Ex: wxString s = _T("Falldog"); // ComposeContent(2, s.c_str(), _T("'s blogger")); wxString ComposeString(int count, ...) { wxString res; va_list vl; va_start(vl, count); for(int i=0 ; i<count ; ++i) res += va_arg(vl,wxChar*); va_end(vl); return res; }
訂閱:
文章 (Atom)