P / Invoke C # struct со строками в C void * - PullRequest
1 голос
/ 23 сентября 2010

У меня проблема с созданием оболочки 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();
}

1 Ответ

3 голосов
/ 23 сентября 2010

Вы можете перегрузить п / вызвать подписи, попробуйте:

[DllImport("LIBRARY.DLL", EntryPoint = "command")]
public static extern int Command(IntPtr Handle, int CommandNum, ref FormatInfoType Data, int DataSize);
...