[英]Passing a pointer to class into unmanaged c++ code from C#
我在dll中有一個c ++導出的函數:
int MyMethod(ulong pid, MyStruct* struct);
MyStruct被描述為類:
class MyStruct
{
public:
uchar nVersion;
uchar nModuleType;
uchar nMachine64;
uchar nReserved;
ulong data1;
ulong data2;
ulong data3;
};
我正在嘗試將此函數導入到我的C#代碼中,如下所示:
[DllImport("mydll.dll", EntryPoint = "#24")]
private static extern int _MyMethod(long pid, ref MyStruct struct);
C#中的類:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
stuct MyStruct
{
public byte nVersion;
public byte nModuleType;
public byte nMachine64;
public byte nReserved;
public ulong data1;
public ulong data2;
public ulong data3;
}
我得到System.AccessViolationException
:
MyStruct struct = new MyStruct();
_MyMethod(4728, ref struct);
怎么了?
更新: System.Runtime.InteropServices.Marshal.SizeOf(struct)
返回32.為什么? 我認為它應該是4 * 1 + 8 * 3 = 28
在C#中,我們有class
es和struct
s。 所有class
類型都是引用,但struct
類型是值類型。 這意味着當你有class MyStruct
並且編寫MyStruct s
它實際上類似於指向基類的指針,當你通過引用傳遞它時,你實際上傳遞了該指針的地址,所以它與期望的C ++無關指向主struct
的指針。 根據這個解決方案你的問題是將class
轉換為struct
。
C#中的long
和ulong
是64位類型,而它們在C ++中是32位(至少是MSVC),因此當您聲明函數使其第一個參數很long
您發送額外的32位值,可能會覆蓋下一個參數並導致它無效:
Stack:
32 bit: [first 32 bit of the first parameter]
32 bit: [second 32 bit of the first parameter]
32 bit: [address of your structure]
因此,當函數調用它時,將使用無效參數作為struct的地址。 所以只需將您的函數定義更改為:
[DllImport("mydll.dll", EntryPoint = "#24")]
private static extern int _MyMethod(int pid, ref MyStruct struct);
你的結構:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
stuct MyStruct
{
public byte nVersion;
public byte nModuleType;
public byte nMachine64;
public byte nReserved;
public uint data1;
public uint data2;
public uint data3;
}
可能是你的錯誤的來源是在函數的第一個參數,因為函數期望一個32位的值,你提供一個64位,實際上你提供2,32位值導致該函數的函數
由於ulong的對齊要求,SizeOf()返回32,這是一個8字節的值類型。 StructLayoutAttribute.Pack的默認值為8,與本機代碼中使用的默認包裝相同。 因此data1與偏移量8對齊,nReserved和data1之間有4個字節的間隙。 所以4 x 1 + 4 + 3 x 8 = 32。
您可能會遇到這種差距,因為在使用MSVC編譯器編譯的本機C ++代碼中,ulong是4個字節。 與C#中的uint相同。 所以修復結構聲明,用uint替換ulong。
下一個問題,即AV的原因,就是你在C#中將結構聲明為一個類。 哪個是始終通過引用傳遞的引用類型。 您當前的聲明等同於C ++代碼中的MyStruct **。 刪除聲明中的引用或將其聲明為結構而不是類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.