Я работаю над .NET DLL для доступа к библиотеке C ++, которую мне дали. В библиотеке C ++ есть такая структура:
typedef struct FOO
{
DWORD DataSize;
BYTE *pData;
}
Я воссоздал его в C # таким образом:
[StructLayout(LayoutKind.Sequential)]
public struct FOO
{
public uint DataSize;
public byte[] pData;
}
Мой импорт из C ++ DLL следующий. Я собираюсь включить заголовок со стороны C ++. Метод в C ++ получает указатель на структуру, которую я передаю, поэтому из того, что я смог собрать, передача ссылки будет работать в этом случае:
// C++ Header
HRESULT CallFoo(FOO * pFoo);
[DllImport("SomeLibrary.DLL", EntryPoint = "CallFoo")]
private static extern uint CallFoo(ref FOO rFoo);
Когда я вхожу в свой код на стороне C ++, я получаю структуру, но значение в pData является адресом памяти. Похоже, что это загрязняет код в библиотеке C ++, но я не могу понять, какой HRESULT он мне возвращает (я задал вопрос владельцу библиотеки C ++ относительно сообщения об ошибке).
Другой подход, который я выбрал, основанный на ответ на этот вопрос, было попробовать передать IntPtr вместо байтового массива. Я изменил структуру:
[StructLayout(LayoutKind.Sequential)]
public struct FOO
{
public uint DataSize;
public IntPtr pData;
}
и назвать это:
FOO fooParm = new Foo();
var ptr = IntPtr.Zero;
byte[] bArr = MethodThatReturnsAByteArray();
ptr = Marshal.AllocHGlobal(bArr.Length);
Marshal.Copy(bArr, 0, ptr, bArr.Length);
fooParm.pData = ptr;
fooParm.DataSize = bArr.Length;
uint i = CallFoo(fooParm);
Это, к сожалению, тоже не работает. Я получаю тот же код ошибки, что и оригинальный подход.
Весь ваш подход не хорош. Существует некоторая информация о компоновке управляемых структур / классов, но лучше ее не использовать. Попробуйте сделать это:
[DllImport("SomeLibrary.DLL", EntryPoint = "CallFoo")]
private static extern uint CallFoo(uint DataSize, IntPtr pData);
Чем больше простых параметров вы передаете туда и обратно, тем лучше будет результат.
У меня нет библиотеки C ++ передо мной, поэтому сложно ответить на этот вопрос точно, я чувствую, но похоже, что вы получаете указатель, и у библиотеки возникают проблемы с этим. Будет ли возможно использовать Marshal::PtrToStructure
чтобы сопоставить это byte[]
указатель на правильный struct
?
Вот ссылка на конкретный метод, о котором я говорю. Второй пример кода в нижней части (в C ++) может применяться: http://msdn.microsoft.com/en-US/library/4ca6d5z7.aspx