[英]Some P/Invoke C# to C marshalling questions working with booleans in structs
我在使用 boolean 類型並在 C# 和 C 之間來回編組時遇到了一些問題。 我在 C 中非常生疏,但希望這部分沒有嚴重錯誤。
As far as I've read/seen, .NET Boolean and C# bool type is 4 bytes long whilst the C type bool is only 1 byte . 由於 memory 占用空間的原因,我不使用 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#中的實際測試function:
[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# 結構,但沒有成功。 所以這是我的問題(1和2最重要):
非常有義務幫助解決這些問題。 我希望他們不要太多。
停止使用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# 中聲明 function :
public static extern void TestGetBackStruct(TestStruct[] structs);
The default marshalling will match your C++ declaration (your code is C++ rather than C in fact) but you must make sure that your allocate the TestStruct[]
parameter in the C# code before calling the function. 通常,您還將數組的長度作為參數傳遞,以便 C++ 代碼知道有多少結構。
請不要嘗試從 function 返回結構數組。 使用structs
參數作為輸入/輸出參數。
我知道沒有一本書強調 P/Invoke。 這似乎是一種黑色藝術!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.