У меня проблема с созданием оболочки C # P / invoke для сторонней библиотеки C.В частности, в библиотеке есть метод с подписью
int command(SomeHandle *handle, int commandNum, void *data, int datasize);
Это метод подстановочных знаков, который выполняет разные действия в зависимости от commandNum.data может быть указателем на что-либо, например, одно целое число, или char [], или какой-либо структурой (моя проблема).
Я объявил обертку следующим образом:
[DllImport("LIBRARY.DLL", EntryPoint = "command")]
public static extern int Command(IntPtr Handle, int CommandNum, [In, Out] IntPtr Data, int DataSize);
Теперь, когда я вызываю его с помощью кода операции для заполнения байта [], это работает:
//WORKS, Buffer contains "library 1.0" after the call
const int BUFFER_SIZE = 128;
byte[] Buffer = new byte[BUFFER_SIZE];
int BytesWritten = 0;
GCHandle BufferHandle = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
try
{
BytesWritten = Command(MyHandle, GET_VERSION, BufferHandle.AddrOfPinnedObject(), BUFFER_SIZE);
}
finally
{
BufferHandle.Free();
}
Однако, когда я пытаюсь сделать то же самое с простой структурой, я не могу заставить ее работать, неважночто я пытаюсьструктура выглядит следующим образом:
public struct FormatInfoType
{
public int Format;
public IntPtr Name; //const char*
public IntPtr Extension; //const char*
}
Здесь я должен заполнить «Format» целым числом (скажем, 1), а затем вызов «command (...)» должен дать мненазад поля имени и расширения
Если я передаю эту структуру, код компилируется и выполняется правильно, но значения в структуре никогда не изменяются.Если я изменяю IntPtr на Strings или StringBuilders (и я пробовал множество атрибутов MarshalAs), то я не могу получить IntPtr в структуру, потому что он становится неблитабельным, а строка GCHandle вызывает исключение.
Любая помощь по этому вопросу будет принята с благодарностью.
РЕДАКТИРОВАТЬ:
Я пробовал много способов вызова command () со структурой, но в настоящее время это выглядиткак это:
FormatInfoType f = new FormatInfoType();
f.Format = 1;
f.Name = IntPtr.Zero;
f.Extension = IntPtr.Zero;
GCHandle fHandle = GCHandle.Alloc(f, GCHandleType.Pinned);
try
{
Command(MyHandle, GET_FORMAT_INFO, fHandle.AddrOfPinnedObject(), Marshal.SizeOf(f));
}
finally
{
fHandle.Free();
}