[英]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.