我正在开发一个项目,其中包括用 C++ 编写的 DLL 和 C# 代码。假设该 DLL 有一个函数:
MyStruct* GetPointer(); // returns pointer to MyStruct structure
MyStruct 结构如下所示:
struct MyStruct
{
OtherStruct1 *data1;
OtherStruct2 *data2;
};
OtherStruct1 和 OtherStruct2 结构如下所示:
struct OtherStruct1
{
public:
double x;
char y;
};
struct OtherStruct2
{
public:
float a;
float b;
float c;
float d;
};
我的问题是 - 在 C# 代码中处理所有这些指针的最佳方法是什么?我所说的“处理”是指读取和写入内存的操作。 C# 中的结构不能简单地包含指针变量。我应该做些什么?最优雅的方式是什么?
您可以使用Microsoft(现已开源)PInvoke 互操作助手将 C/C++ 代码转换为 C# 或 VB 的工具。运行示例代码给出:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct MyStruct {
/// OtherStruct1*
public System.IntPtr data1;
/// OtherStruct2*
public System.IntPtr data2;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct OtherStruct1 {
/// double
public double x;
/// char
public byte y;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct OtherStruct2 {
/// float
public float a;
/// float
public float b;
/// float
public float c;
/// float
public float d;
}
public partial class NativeMethods {
/// Return Type: MyStruct*
[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="GetPointer")]
public static extern System.IntPtr GetPointer() ;
}
将 DllImportAttribute 中的“Unknown”替换为您的 dll 名称,并确保在项目中引用它。您现在应该能够在托管代码中访问您的结构。
然后,要从内存中读取/写入,您将需要使用 System.Runtime.InteropServices.Marshal 命名空间中的方法。以下代码片段展示了如何使用 GetPointer 函数将非托管结构转换为托管结构:
IntPtr myPtr = NativeMethods.GetPointer(); // Call native code to retrieve pointer to unmanaged memory where the struct lives
MyStruct myStruct = new MyStruct(); // Create a new managed struct
myStruct = Marshal.PtrToStructure<MyStruct>(myPtr);
以下是将托管结构传递给非托管方法的方法:
MyStruct myStruct = new MyStruct(); // Create the managed struct
myStruct.data1 = new OtherStruct1(); // Create a managed OtherStruct1
myStruct.data2 = new OtherStruct2(); // Create a managed OtherStruct2
IntPtr myStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf<MyStruct>()); // Allocate unmanaged memory for the struct
Marshal.StructureToPtr<MyStruct>(myStruct, myStructPtr, false);
try
{
NativeMethodThatUsesMyStructPtr(myStructPtr);
}
finally
{
Marshal.FreeHGlobal(myStructPtr); // *** You have to free unmanaged memory manually, or you will get a memory leak! ***
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)