最近在接SDK,在寫DllImport遇到一個神奇的暗坑
export代碼和DLLImport
#if defined(_WIN32) || defined(_WIN64)
#define __DLLEXPORT__ __declspec(dllexport)
#else
#define __DLLEXPORT__
#endif
extern "C"
{
__DLLEXPORT__
void Init(size_t* requiredSize,char* buff)
{
....
}
}
[DllImport("SDK")]
public static extern void Init(ref int requiredSize);
DLL是64位,測驗代碼如下
int a = 1;
StringBuilder sb = new StringBuilder(1024);
Init(ref a, sb);
print(a);print(sb);
結果驚奇的發現sb = NULL
換了段測驗代碼
int a = 1;
StringBuilder sb1 = new StringBuilder(1024);
StringBuilder sb2 = new StringBuilder(1024);
Init(ref a, sb2);
print(a);print(sb1);print(sb2);
發現sb2的資料是正常的,sb1依舊是NUll
和同事研究了一下,最后發現是DllImport寫得不對
換成以下寫法就正常了
[DllImport("SDK")]
public static extern void Init(ref UIntPtr requiredSize);
導致這個bug的原因是因為size_t的跨平臺性,C#下于它匹配的資料型別是UIntPtr,同樣可以做到32位系統是4位元組,64位系統是8位元組,而且都是Unsigned Int
原來的寫法之所以會出現例外奇怪的bug是因為c++的方法會將requiredSize置空后再賦值,
而C#下由于a和sb資料是連續的,2個加起來位元組數才能和size_t對等,結果導致了sb也被置空,真是危險的c++
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/50942.html
標籤:C#
