У меня есть некоторые проблемы при работе с булевыми типами и их распределении в структуре между C # и C. Я очень ржавый в C, но, надеюсь, в этой части нет ничего принципиально неправильного.
Насколько я читал / видел, тип .NET Boolean и C # bool имеет длину 4 байта , а тип C bool составляет всего 1 байт .По причинам, связанным с объемом памяти, я не могу использовать определенную версию BOOL 4 байта в коде C .
Вот простой тестовый код, который, надеюсь, прояснит мои вопросы:
Код 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 # без успеха.Итак, вот мои вопросы (1 и 2 наиболее важные):
- Корректна ли функция C для этой цели?
- Как структурабыть написанным правильно, чтобы вернуть мне правильные значения в структуре обратно в C #? (необходимо ли даже определять структуру с помощью атрибута StructLayout (LayoutKind.Explicit), используя значения FieldOffset, или я могу использовать StructLayout (LayoutKind.Sequential) вместо)?
- Поскольку я возвращаю указатель на TestStruct в C, я думаю, что должна быть возможность вернуть массив TestStructs в C # .Но это не представляется возможным при использовании функции Marshal.PtrToStructure.Будет ли это возможно каким-то другим способом?
- Очевидно, что в C можно использовать то, что называется объединениями, если несколько структурных полей указывают на одно и то же выделение памяти с использованием одного и того же значения атрибута FieldOffset.Я понимаю это, но я все еще еще не понимаю, когда такой сценарий будет полезен .Пожалуйста, просветите меня.
- Может ли кто-нибудь порекомендовать хорошую книгу по C # P / Invoke для C / C ++? Я немного устаю получать кое-какую информацию здесь и там наИнтернет.
Большое спасибо за помощь по этим вопросам.Надеюсь, их было не так уж много.