我在使用布尔类型时遇到了一些问题,并在C#和C之间来回地在一个结构中编组它。我在C中非常生疏,但希望那部分没有任何重大错误。
据我所知,.NET Boolean和 C#bool类型长4个字节,而 C类型bool只有1个字节。出于内存占用的原因,我没有在C代码中使用定义的BOOL 4字节版本。
以下是一些简单的测试代码,希望能够清楚地解答我的问题:
C代码:
typedef struct
{
double SomeDouble1;
double SomeDouble2;
int SomeInteger;
bool SomeBool1;
bool SomeBool2;
} TestStruct;
extern "C" __declspec(dllexport) TestStruct* __stdcall TestGetBackStruct(TestStruct* structs);
__declspec(dllexport) TestStruct* __stdcall TestGetBackStruct(TestStruct* structs)
{
return structs;
}
我使用以下定义在C#中调用此代码:
[StructLayout(LayoutKind.Explicit)]
public struct TestStruct
{
[FieldOffset(0)]
public double SomeDouble1;
[FieldOffset(8)]
public double SomeDouble2;
[FieldOffset(16)]
public int SomeInteger;
[FieldOffset(17), MarshalAs(UnmanagedType.I1)]
public bool SomeBool1;
[FieldOffset(18), MarshalAs(UnmanagedType.I1)]
public bool SomeBool2;
};
[DllImport("Front.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr TestGetBackStruct([MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] TestStruct[] structs);
这是C#中的实际测试函数:
[Test]
public void Test_CheckStructParsing()
{
var theStruct = new TestStruct();
theStruct.SomeDouble1 = 1.1;
theStruct.SomeDouble2 = 1.2;
theStruct.SomeInteger = 1;
theStruct.SomeBool1 = true;
theStruct.SomeBool2 = false;
var structs = new TestStruct[] { theStruct };
IntPtr ptr = TestGetBackStruct(structs);
var resultStruct = (TestStruct)Marshal.PtrToStructure(ptr, typeof(TestStruct));
}
这可以理解为我得到一个结构(使用调试器来检查它),但是值完全错误。即编组根本不起作用。我尝试过不同版本的C#struct而没有成功。所以这是我的问题(1& 2最重要):
非常有必要帮助解决这些问题。我希望他们不是太多。
答案 0 :(得分:6)
停止使用LayoutKind.Explicit
并删除FieldOffset
属性,您的代码将起作用。您的偏移量没有正确对齐字段。
public struct TestStruct
{
public double SomeDouble1;
public double SomeDouble2;
public int SomeInteger;
[MarshalAs(UnmanagedType.I1)]
public bool SomeBool1;
[MarshalAs(UnmanagedType.I1)]
public bool SomeBool2;
};
在C#中声明函数,如下所示:
public static extern void TestGetBackStruct(TestStruct[] structs);
默认编组将与您的C ++声明匹配(您的代码实际上是C ++而不是C)但您必须确保在调用函数之前在C#代码中分配TestStruct[]
参数。通常,您还会将数组的长度作为参数传递,以便C ++代码知道有多少个结构。
请不要尝试从函数返回结构数组。使用structs
参数作为输入/输出参数。
我知道没有一本强调P / Invoke的书。它似乎是一种黑色艺术!