将指针从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
。
long
和C#中的ulong
是64位类型,而C 中的32位(MSVC至少为MSVC),因此当您声明函数以使其第一个参数为long
时,您会发送额外的32位值,该额外的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位值
sizeof()返回32,因为对8个字节值类型Ulong的对齐要求。structlayoutattribute.pack的默认值为8,与本机代码中使用的默认包装相同。因此,Data1被对齐以抵消8,并且在NERVERDER和DATAID 1之间存在4个字节差距。因此4 x 1 4 3 x 8 = 32。
您可能会遇到差距,因为在与MSVC编译器编译的本机C 代码中,ulong为4个字节。与C#中的UINT相同。因此,修复结构声明,用UINT代替Ulong。
下一个问题,即AV的原因,是您将结构声明为C#中的类。这是一种始终通过参考传递的参考类型。您当前的声明等效于C 代码中的Mystruct **。在声明中删除 ref ,或将其声明为结构而不是类。
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 如何防止C++遗留代码中的挂起指针
- 理解这行C++指针代码
- 为什么我们不在下面给出的代码中使用指针来实例化C++的实体对象?
- 为什么我的代码在指针方面停止运行?
- 以下与指针相关的代码的输出是什么?
- C++指针问题:如何修复这些代码中的错误?
- 如何使用指针直接从托管代码中的非托管代码中读取矢量数据
- 为什么下面的代码段返回指针指向的值而不是指针的地址?
- 使用指针向量(带代码)C++(以及对其使用的便利性的怀疑)时出现问题
- 为什么从 constexpr 引用生成的程序集代码与从 constexpr 指针生成的程序集代码不同?
- 由于指针算法错误,代码在 memcpy 中崩溃
- 为什么通过定义另一个指针单元格,整个代码停止工作?
- 使用指针编译代码后,.cpp文件将变为随机字符
- OpenCV如何处理Mat作为指针来加速代码
- 更正代码c++指针并删除
- C++指向对象的指针堆数组中,如何将字符串传递给特定对象?有一些代码请看一下:
- C++ 被此代码与多态性、指针和对象切片混淆
- LLvm Jit:如何从抖动代码中取消引用运行时指针?
- 将 C 代码移植到C++,将 void* 从 malloc 转换为所需指针的问题