Проблема, вероятно, в вашей первой структуре.Определение C ++ включает указатель на буфер данных, но маршаллер не может напрямую преобразовать это в .NET byte[]
(или, идя в другом направлении, он, вероятно, преобразует byte[]
в недопустимый указатель, таким образом, ваши недопустимые параметрыошибка).Вместо этого вы можете сделать это вручную в два этапа:
[StructLayout(LayoutKind.Sequential)]
public struct DATA_BUFFER
{
public IntPtr buffer;
public uint length;
}
и затем прочитать буфер вручную, используя Marshal
(это просто быстрый пример из моей памяти API Marshal
):
var txBufBytes = new byte[pComm.TxBuf.length];
Marshal.Copy(pComm.TxBuff.buffer, 0, pComm.TxBuf.length);
Кроме того, как @svick упомянул в комментариях, вам, вероятно, потребуется установить CharSet
в CharSet.Ansi
, если ваш нативный код принимает не-юникод / широкие символы.
Наконец, определение C ++ второй структуры, похоже, определяет одноэлементные массивы, которые, в свою очередь, могут фактически быть указателями, а не иметь структуры в памяти.В этом случае вам, вероятно, придется заменить определение, чтобы использовать IntPtr
s для взаимодействия, а затем использовать Marshal.PtrToStructure
для получения фактических структур.
Вы должны по крайней мере сравнить, что размеры структурто же самое, сравнивая результаты sizeof(...)
в C ++ с Marshal.SizeOf(...)
в C # для определений структуры.
Учитывая то, что вы сказали в комментариях, вы сможете использовать модификацию DATA_BUFFER
Я описал выше, и оригинальное определение структуры, которое вы использовали для JVM_COMM_BUFFER
[StructLayout(LayoutKind.Sequential)]
struct JVM_COMM_BUFFER
{
public DATA_BUFFER TxBuf;
public DATA_BUFFER RxBuf;
}
, объедините это с небольшим изменением вашего DllImport
[DllImport("jhi.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern UInt32 SendAndRecv(IntPtr handle, string AppId, [In, Out] ref JVM_COMM_BUFFER pComm);
CharSet.Ansi
важнодля гарантии того, что ваша строка .NET будет правильно распределена в строку ANSI (при условии, что ваша нативная функция C не ожидает тип строки wchar_t
).Атрибуты [In, Out]
могут не требоваться, но могут указывать маршаллеру, как правильно управлять этим параметром.
Если JVM_COMM_BUFFER
действительно INOUT
, и вы предварительно заполняете его даннымиперед вызовом функции может потребоваться убедиться, что все данные верны.Вызываемая функция может иметь документацию о том, какие значения она ожидает от своих параметров.Однако приведенные здесь определения должны корректно распределяться на основе предоставленных вами определений C ++.