[英]How to marshal a structure containing a union from C to C#
有人可以帮我解决以下问题吗?
我有一个用 C 编写的 dll,想从 C# 调用其中的某个函数。
该函数返回一个指向结构的指针。 这是结构:
typedef struct
{
char crv_name[40];
char crv_name2[12];
char units[40];
char creator[24];
char index_units[8];
double first_dep_tim;
double last_dep_tim;
double level_spacing;
EmptyValU empty_val;
long num_ele;
}
现在,我知道(从 C 客户端调用它)最后一个成员 (num_ele) 将被设置为 1。
现在,倒数第二个成员是 EmptyValU 类型,定义为:
typedef union
{
double d;
float f;
long l;
ulong ul;
short s;
ushort us;
char c;
}EmptyValU;
现在,我可以在 C# 中调用它并读取所有内容,直到 empty_val。 我对 num_ele 的值是无稽之谈,因为在 empty_val 之后我在内存中显然没有对齐。
这是我的 C# 代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CurveInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string crv_name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string crv_name2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
public string units;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string creator;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string index_units;
public double first_dep_tim;
public double last_dep_tim;
public double level_spacing;
[MarshalAs(UnmanagedType.Struct, SizeConst = 8)]
public EmptyValU empty_val;
public long num_ele;
}
我将 EmptyValU 定义为:
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct EmptyValU
{
[FieldOffset(0)]
public double d;
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
long l;
[FieldOffset(0)]
ulong ul;
[FieldOffset(0)]
short s;
[FieldOffset(0)]
ushort us;
[FieldOffset(0)]
char c;
}
就像我说的,当我调用返回指向这种结构的指针的函数时,所有值都被正确填充,直到 EmptyValU 成员,以及 num_ele 没有正确填充。 为了保持对齐正确,我必须在 C# 中定义联合的方式是我所缺少的。
感谢您的帮助,米奇。
我已经解决了这个问题。
IC,long(和 ulong)是 4 个字节宽,但在 C# 中它们是 8 个字节宽。
所以而不是:
[FieldOffset(0)]
long l;
[FieldOffset(0)]
ulong ul;
我应该有:
[FieldOffset(0)]
int l;
[FieldOffset(0)]
uint ul;
因为在 C# 中 int 和 uint 是 4 个字节宽。
出于同样的原因,在 C# 端而不是:
public long num_ele;
我需要:
public int num_ele;
现在一切正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.