C# 将结构的数组封送到Ptr
我正在从C代码调用C库。我调用的函数将包含struct数组的struct作为参数:C# 将结构的数组封送到Ptr,c#,C#,我正在从C代码调用C库。我调用的函数将包含struct数组的struct作为参数: struct Example1Struct { char* a; uint16_t b; AnotherStruct* c; } 这里是指向另一个结构的指针数组 我的C代码中的结构如下所示 public struct Example1Struct { public IntPtr StationName;//is c
struct Example1Struct
{
char* a;
uint16_t b;
AnotherStruct* c;
}
这里是指向另一个结构的指针数组
我的C代码中的结构如下所示
public struct Example1Struct
{
public IntPtr StationName;//is char*
public UInt16 IdCode;
public IntPtr AnotherStruct; //array of struct AnotherStruct
}
public static IntPtr MarshalToPointer(object data)
{
Type valueType = data.GetType();
IntPtr buf = IntPtr.Zero;
if (valueType.IsArray)
{
if (data is char[])
{
var d = data as char[];
buf = Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType()) * d.Length);
}
else if (data is char[,])
{
var d = data as char[,];
buf = Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType()) * d.Length);
}
else
{
buf = Marshal.AllocHGlobal(Marshal.SizeOf(data.GetType().GetElementType()) * count);
long LongPtr = buf.ToInt64(); // Must work both on x86 and x64
for (int I = 0; I < data.Lenght; I++)
{
IntPtr RectPtr = new IntPtr(LongPtr);
Marshal.StructureToPtr(data[I], RectPtr, false); // You do not need to erase struct in this case
LongPtr += Marshal.SizeOf(typeof(Rect));
}
}
return buf;
}
else
buf = Marshal.AllocHGlobal(Marshal.SizeOf(data));
Marshal.StructureToPtr(data, buf, false);
return buf;
}
公共结构示例1结构
{
public IntPtr StationName;//是字符*
公共UInt16识别码;
public IntPtr AnotherStruct;//struct AnotherStruct的数组
}
公共静态IntPtr MarshallTopoInter(对象数据)
{
类型valueType=data.GetType();
IntPtr buf=IntPtr.0;
if(valueType.IsArray)
{
if(数据为字符[])
{
var d=数据为字符[];
buf=Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType())*d.Length);
}
else if(数据为字符[,])
{
var d=数据为字符[,];
buf=Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType())*d.Length);
}
其他的
{
buf=Marshal.AllocHGlobal(Marshal.SizeOf(data.GetType().GetElementType())*count);
long LongPtr=buf.ToInt64();//必须同时在x86和x64上工作
对于(int I=0;I
这里的问题是,我无法将数据(另一个结构的数组)强制转换为对象[],IEnumerable中也不能。因此,我无法访问数据[I],并且没有数据。长度
有什么想法吗?你可以这样得到数组的长度:
if (data is Array a)
Console.WriteLine(a.Length);
c#中的数组总是派生自数组
,因此您可以将其强制转换为该数组
但是如果可能,在实际代码中,我建议使用属性,而不是编写手动编组代码。它看起来像:
public struct Example1Struct
{
public IntPtr StationName;//is char*
public UInt16 IdCode;
public IntPtr AnotherStruct; //array of struct AnotherStruct
}
可以是:
public struct Example1Struct
{
[MarshalAs(UnmanagedType.LPStr)]
public string StationName;
public UInt16 IdCode;
[MarshalAs(UnmanagedType.LPArray)]
public AnotherStruct[] OtherStructs;
}
当您将其传递给非托管代码时,封送处理程序应该为您做正确的事情。您是否考虑过将
marshallas
属性应用于您的结构?让封送拆收器处理分配等[Marshallas(UnmanagedType.LPArray)]在运行时给我以下错误:System.TypeLoadException:“无法封送类型为“AnotherStruct”的字段“OtherStructs”:无效的托管/非托管类型组合(数组字段必须与ByValArray或SafeArray成对)。”