簡體   English   中英

將指向class的指針傳遞給C#中的非托管c ++代碼

[英]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#中的longulong是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM