我在 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
和 struct
。所有 class
类型都是引用,但 struct
类型是值类型。这意味着当你有类似 class MyStruct
的东西并且你写 MyStruct s
它实际上就像一个指向基类的指针,当你通过引用传递它时你实际上传递了地址该指针的一部分,因此它与期望指向主 struct
的指针的 C++ 无关。根据此解决方案,您的问题是将 class
转换为 struct
。
long
和 ulong
在 C# 中是 64 位类型,而在 C++(至少 MSVC)中它们是 32 位类型,所以当你声明你的函数时,它的第一个参数是 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]
所以当函数被调用时,它会将一个无效的参数作为结构的地址。所以只需将您的函数定义更改为:
[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 位值
关于c# - 将指向类的指针从 C# 传递到非托管 C++ 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12978160/