Да, функции, которые возвращают структуру, как правило, трудны для взаимодействия.Такая структура должна быть blittable , чтобы маршаллер pinvoke мог передать указатель на функцию, готовый записать возвращаемое значение.Быть «легкомысленным» означает, что структура структуры в управляемом коде должна быть идентична неуправляемой структуре структуры.Если это не так, то копия должна быть сделана, маршаллер pinvoke не хочет делать эту копию в конкретном случае возвращаемого значения.
Тип bool
является проблемой взаимодействия, выполняются разные среды выполненияразные варианты.Обычно он составляет 4 байта в C (сравните с типом Windows BOOL, также по умолчанию для pinvoke), 2 байта в COM-взаимодействии (он же VARIANT_BOOL), 1 байт в C ++, 1 байт в CLR.Поскольку целевое время выполнения неизвестно, CLR не может угадать, какой выбор правильный.BOOL по умолчанию, 4 байта.
Даже использование [MarshalAs(UnmanagedType.U1)]
для принудительного точного совпадения не делает его слепым.Что довольно странно, я считаю это ошибкой CLR.Хороший обходной путь - заменить его на byte
, вы можете использовать свойство, чтобы обернуть его обратно в bool.Помните, что в опубликованном фрагменте было много ошибок, я заставил эту версию работать:
using System;
using System.Runtime.InteropServices;
class Program {
static void Main(string[] args) {
Foo value = GetFoo();
}
[StructLayout(LayoutKind.Sequential)]
private struct Foo {
public int a;
private byte _b;
public bool b {
get { return _b != 0; }
}
public int c;
};
[DllImport(@"c:\projects\consoleapplication3\debug\cpptemp10.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_GetFoo@0")]
private static extern Foo GetFoo(/*int CoreIndex*/);
}
typedef struct foo
{
int a;
bool b;
int c;
} FOO,*LPFOO;
extern "C" __declspec(dllexport)
FOO __stdcall GetFoo()
{
FOO f;
f.a = 42;
f.b = true;
f.c = 101;
return f;
}