简体   繁体   English

将指向class的指针传递给C#中的非托管c ++代码

[英]Passing a pointer to class into unmanaged c++ code from C#

I have a c++ exported function in dll: 我在dll中有一个c ++导出的函数:

int MyMethod(ulong pid, MyStruct* struct);

MyStruct is described as class: MyStruct被描述为类:

class MyStruct
{
public:
uchar   nVersion;
uchar   nModuleType;
uchar   nMachine64;
uchar   nReserved;
ulong  data1;
ulong  data2;
ulong  data3;
};

I'm trying to import this function to my C# code like this: 我正在尝试将此函数导入到我的C#代码中,如下所示:

[DllImport("mydll.dll", EntryPoint = "#24")]
private static extern int _MyMethod(long pid, ref MyStruct struct);

Class in C#: 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;
}

And i'm getting System.AccessViolationException : 我得到System.AccessViolationException

MyStruct struct = new MyStruct();
_MyMethod(4728, ref struct);

What's wrong? 怎么了?

UPDATE: System.Runtime.InteropServices.Marshal.SizeOf(struct) returns 32. Why? 更新: System.Runtime.InteropServices.Marshal.SizeOf(struct)返回32.为什么? I thought it should be 4 * 1 + 8 * 3 = 28 我认为它应该是4 * 1 + 8 * 3 = 28

In C# we have class es and struct s. 在C#中,我们有class es和struct s。 All class types are reference but struct types are value types. 所有class类型都是引用,但struct类型是值类型。 This means when you have something like class MyStruct and you write MyStruct s it is actually something like a pointer to base class, and when you pass it by reference you actually pass address of that pointer, so it has nothing to do with C++ that expect a pointer to main struct . 这意味着当你有class MyStruct并且编写MyStruct s它实际上类似于指向基类的指针,当你通过引用传递它时,你实际上传递了该指针的地址,所以它与期望的C ++无关指向主struct的指针。 According to this solution to your problem is to convert class to struct . 根据这个解决方案你的问题是将class转换为struct

long and ulong in C# are 64 bit types while they are 32 bit in C++(MSVC at least), so when you declare your function such that its first parameter is long you send extra 32 bit value that may override next parameter and cause it to be invalid: 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]

So when function called it will take an invalid parameter as address of struct. 因此,当函数调用它时,将使用无效参数作为struct的地址。 so just change your function definition to: 所以只需将您的函数定义更改为:

[DllImport("mydll.dll", EntryPoint = "#24")]
private static extern int _MyMethod(int pid, ref MyStruct struct);

An your struct to: 你的结构:

[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;
}

may be source of your error is in first parameter of the function, because function expect a 32 bit value and you provide a 64 bit one and actually you provide 2, 32 bit value to the function that cause the function 可能是你的错误的来源是在函数的第一个参数,因为函数期望一个32位的值,你提供一个64位,实际上你提供2,32位值导致该函数的函数

SizeOf() returns 32 because of the alignment requirements for ulong, an 8 byte value type. 由于ulong的对齐要求,SizeOf()返回32,这是一个8字节的值类型。 The default value for StructLayoutAttribute.Pack is 8, same as the default packing used in native code. StructLayoutAttribute.Pack的默认值为8,与本机代码中使用的默认包装相同。 So data1 gets aligned to offset 8 and there's a 4 byte gap between nReserved and data1. 因此data1与偏移量8对齐,nReserved和data1之间有4个字节的间隙。 So 4 x 1 + 4 + 3 x 8 = 32. 所以4 x 1 + 4 + 3 x 8 = 32。

You probably got that gap because in native C++ code compiled with the MSVC compiler, an ulong is 4 bytes. 您可能会遇到这种差距,因为在使用MSVC编译器编译的本机C ++代码中,ulong是4个字节。 Same as uint in C#. 与C#中的uint相同。 So fix the structure declaration, replace ulong with uint. 所以修复结构声明,用uint替换ulong。

Next problem, the cause of the AV, is that you declared the structure as a class in C#. 下一个问题,即AV的原因,就是你在C#中将结构声明为一个类。 Which is a reference type which always gets passed by reference. 哪个是始终通过引用传递的引用类型。 Your current declaration is equivalent to MyStruct** in C++ code. 您当前的声明等同于C ++代码中的MyStruct **。 Either remove the ref in the declaration or declare it as a struct instead of a class. 删除声明中的引用或将其声明为结构而不是类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM