繁体   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