将c++结构体转换为c#并使用它
本文关键字:c++ 结构体 转换 | 更新日期: 2023-09-27 17:54:05
我有一个c++结构体如下:
struct Vehicle
{
u32 something;
Info *info;
u8 something2[ 0x14 ];
Vector3f location;
Template* data;
};
struct Info
{
u32 speed;
std::string name;
BuffCollection** buffCollection;
void* sectionPtr;
};
struct Template
{
u32 templateID;
};
从这个问题中,我弄明白了u32, u8等的含义,或者我认为我做到了。
然后我试着用它来创建我自己的c#结构体:
[StructLayout(LayoutKind.Sequential)]
public struct Vehicle
{
public uint Something;
public Info Info;
public byte Something2;
public Vector3f Location;
public Template Data;
}
[StructLayout(LayoutKind.Sequential)]
public struct Info
{
public uint Speed;
public string Name;
public byte[] BuffCollection;
public IntPtr SectionPointer;
}
[StructLayout(LayoutKind.Sequential)]
public struct Template
{
public uint TemplateId;
}
public struct Vector3f
{
public float X, Y, Z;
public Vector3f(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
然而,当我试图读取Vehicle:
[DllImport("Core.dll")]
static extern Vehicle GetVehicle();
static void Main()
{
var vehicle = GetVehicle();
Console.WriteLine(vehicle.Info.Name);
Console.ReadKey();
}
我得到以下错误:
System.Runtime.InteropServices.MarshalDirectiveException: Method's type signature is not PInvoke compatible
从我对它的搜索来看,它使我相信我的结构转换是错误的。
- 我的转换结构有什么问题?
结构:
-
Vehicle.Info
是一个指针,所以需要声明为IntPtr Info
,然后在托管代码中使用Marshal.PtrToStructure / Marshal.StructureToPtr
读写它的值; -
Vehicle.something2
是一个字节数组,而不是字节,所以你需要这样声明它:[MarshalAs UnmanagedType。ByValArray SizeConst = 20)]
-
Vehicle.Data
-见#1,同样的问题 -
Info.Name
- . net不提供std::string的封送处理,所以你要么需要编写自己的封送处理(参见:自定义封送处理PInvoke with std::string),要么在你的c++库中将类型更改为char*之类的东西。 -
Info.BuffCollection
也应该是IntPtr或BuffCollection[](取决于BuffCollection类型是什么-它没有在你的问题中提供)
关于GetVehicle();
方法的签名和调用:
很可能该方法返回的是指向结构体的指针,而不是结构体本身(只是推测,请仔细检查)。如果是,您需要将其声明为
static extern IntPtr GetVehicle();
,然后使用Marshal.PtrToStructure
将其转换为您的结构,如下所示:
var vehiclePtr=GetVehicle();
var vehicle = (Vehicle)Marshal.PtrToStructure(vehiclePtr, typeof(Vehicle));