Как вызвать функцию C в DLL из C #? - PullRequest
0 голосов
/ 14 февраля 2019

Мне нужно вызвать следующую функцию C, импортируя DLL в C #, но она выдает следующую ошибку:

Я импортировал DLL и успешно выполнил другие функции, пока эта функция выдает ошибку.

C Метод:

long __stdcall VBVMR_Input_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId);

C # Код:

[DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_Input_GetDeviceDescA", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern int VBVMR_Input_GetDeviceDescA(long zindex, ref long nType, [Out] byte[] szDeviceName, [Out] byte[] szHardwareId);

long nType = 0;
byte[] c = new byte[100];
byte[] b = new byte[100];
long i=0;

int rep = VBVMR_Input_GetDeviceDescA(i,ref nType, c, b);

Выдает исключение при выполнении VBVMR_Input_GetDeviceDescA как:

При вызове функции PInvoke 'Voicemeter!Voicemeter.Program::VBVMR_Input_GetDeviceDescA' разбалансирован стек.Это вероятно потому, что управляемая подпись PInvoke не совпадает с неуправляемой целевой подписью.Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

1 Ответ

0 голосов
/ 14 февраля 2019

Если ваша экспортируемая функция объявлена ​​с соглашением о вызовах __stdcall в DLL, которая ее экспортирует, вам нужно импортировать ее в код C # с CallingConvention.StdCall, а не Cdecl.

Причиначто это несоответствие соглашения о вызовах выдает ошибку о "разбалансировке стека", потому что после вызова функции cdecl вызывающий код должен корректировать регистр указателя стека после вызова функции, чтобы удалить параметры, переданные функции изстек.Однако, поскольку ваша функция на самом деле является функцией stdcall, она сама выполняет это в используемой инструкции ret imm16, поэтому ваш стек теряет память, когда вызывающий код тоже «очищает стек».

Следующийпроблема в том, что long в C # и long в MSVC имеют разные размеры, поэтому даже при соглашении о вызовах stdcall вызываемая функция выдает количество байтов, соответствующее тому, что она считает правильным размером для списка параметров,но, поскольку long в C # не совпадает с размером long в MSVC, стек все еще не сбалансирован после инструкции ret imm16 в конце функции DLL.Тип C # int соответствует long, однако.

...