我正在爲C++ API編寫一個C#封裝器,但依賴於這個結構的特定結構和函數在調試時給出了非常奇怪的錯誤。來自PInvoke結構/函數的奇數錯誤
C++結構:
typedef struct
{
unsigned __int handle;
char name[80];
unsigned int unique_ID;
} DeviceInfo;
跟此功能:
int __stdcall get_device_info(DeviceInfo di[], const int length_of_di_array, int* p_numValidDevices);
的結構和功能被導入爲,例如:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DeviceInfo
{
public UInt32 handle;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 80)]
public String name;
public UInt32 unique_ID;
}
[DllImportAttribute("MyC++API.dll", EntryPoint = "get_device_info", CallingConvention = CallingConvention.StdCall)]
public static extern int get_device_info(ref DeviceInfo di, int length_of_di_array, ref numValidDevices);
預期用途這個結構和功能的只是爲了從電路板Im訪問獲取一些設備信息。目前我無法訪問C++中的函數體,所以我只能假定它工作在100%(在C++中工作正常)。
問題是,當我使用該函數來運行一個結構數組時,它輸出我正在查找的數據,但也會在運行時開始失敗,並給我提供各種錯誤窗口。
C#代碼:
static void Main()
{
int numValidDevices = 0; //initialize variable
DeviceInfo[] di = new DeviceInfo[16]; //max of 16 devices
for (int i = 0; i < numValidDevices; ++i) //sorts through all validated devices
{
rc = get_device_info(ref di[i], 16, ref numValidDevices); //accesses each device element and returns the data
Console.WriteLine("Handle: {0}\nName: {1}\nUnique ID: {2}", di[i].handle, di[i].name, di[i].unique_ID);
}
Console.ReadLine(); //stops console from closing prematurely
API_close(); //custom close function from the C++ API
}
錯誤在調試(信息仍示出): 「類型 'System.Threading.ThreadStateException' 的未處理的異常發生在System.dll中
其他信息:線程尚未啓動。「
「類型‘System.ExecutionEngineException’的未處理的異常出現在mscorlib.dll」
錯誤在調試(信息不被示出,程序執行失敗): 「未處理的異常類型的「系統。 AccessViolationException'發生在mscorlib.dll中
附加信息:嘗試讀取或寫入受保護的內存,這通常表示其他內存已損壞。
關閉控制檯窗口時: 「'0x7c9113c0'處的指令引用內存'0x00000000',內存不能被'寫入'。 (有時會說'讀'而不是'寫')。
我已經做了很多研究的PInvoke和整個Microsoft InteropAssistant application來了,因爲這樣this one各種堆棧溢出文章,this post似乎更接近到什麼Im做,但我還是挖掘到了如何使用元帥.CoTaskMemAlloc/Free,看看它是否會做任何...
到目前爲止,我對我的結構和函數是正確的,我試着改變結構使用IntPtr,但不返回di.name值和di.unique_ID變成亂碼(奇怪的是,di。手柄保持有效)
C#代碼:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DeviceInfo
{
public UInt32 handle;
IntPtr p_name;
public String name { get { return Marshal.PtrToStringAnsi(p_name); } }
public UInt32 unique_ID;
}
預期輸出:
Handle: 3126770193
Name: DEVICE_A
Unique ID: 12345678
IntPtr的輸出:
Handle: 3126770193
Name:
Unique ID: 1145128264
奇怪的是,使用沒有錯誤的一個IntPtr結果以上,運行良好。 這使我相信問題在於將C++字符串編組爲字符串,但我不確定問題出在編組,內存管理(沒有?),還是我沒有完全捕獲。
任何和所有的反饋意見將非常感激,我已經難倒這個數週的現在......
您正在傳遞一個引用,但它期望一個數組。 – leppie
還要確保C中的'sizeof'大於C中的C#=='sizeof'我懷疑名稱是錯誤的。請嘗試使用byte []並應用值數組大小常量。 – leppie
而不是編輯問題,你應該發佈一個答案。你願意這樣做嗎? –