我有一些問題處理布爾類型,並在C#和C之間來回編譯這個結構。我在C中生鏽,但希望沒有什麼關鍵那部分是錯誤的。一些P/Invoke C#到C編組問題在結構中使用布爾值
據我讀過/看出,.NET布爾和C#bool類型是4個字節長而C類布爾僅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);
a ND這裏是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));
}
這工作,因爲我得到一個struct回(使用調試器來檢查它)的意義上說,但是完全錯誤的價值觀。即編組根本不起作用。我嘗試過不同版本的C#結構,但沒有成功。因此,這裏是我的問題(1 & 2最重要的):
- 是C函數正確,此目的是什麼?
- 如何正確地寫入結構以便將結構中的正確值返回給C#?(甚至有必要使用FieldOffset值來定義具有StructLayout(LayoutKind.Explicit)屬性的結構,還是可以使用StructLayout(LayoutKind.Sequential))?
- 由於我返回了一個指向C中TestStruct的指針,我猜應該有可能在C#中得到TestStructs的一個數組。但是使用Marshal.PtrToStructure函數似乎不可能。有可能以其他方式嗎?
- 通過使用相同的FieldOffset屬性值使多個結構字段指向相同的內存分配,可以使用名爲聯合的C中的某些東西。我明白這一點,但我仍然還沒有得到,當這種情況下會有用。請賜教。
- 是否有人推薦一本關於C#P /調用C/C++的好書?我有點厭倦了在網上獲取各種信息。
非常感謝您對這些問題的幫助。我希望他們不是太多。
參數不是一個真正的數組。它應該被宣佈爲'out TestStruct retval' –
感謝您的信息!但是我確實認爲我正在分配TestStruct []參數:var structs = new TestStruct [] {theStruct};在調用函數之前。另外,我注意到,在resultStruct上的所有結構字段的末尾添加Console.WriteLine時,所有參數(預計整數)實際上都會正確返回。但調試器仍然提供完全關閉的值。那是怎麼回事? :(而且,quriosity殺死了這個貓:是什麼讓我的代碼比C更像C++? – Toby999
'extern「C」'是一個告訴符號。你實際上是否需要一個結構數組,或者像@Hans所說的那樣你只需要一個單獨的項目? –