Как я могу преобразовать это объявление процедуры Clarion в С#? Это часть DLL третьей стороны, написанная на C, которая не имеет большой документации. Я перечислил прототип метода в Clarion, который работает правильно. В С# я не уверен, какой тип использовать для замены *CString
. Я попробовал char[]
как @DanielC, но это не сработало. Я также обнаружил, что Clarion long
является 32-битным (спасибо @shf301).
Clarion:
SendRequest Procedure(*CString xData,Long DataLen,Long xTimeout),Byte,Virtual
С# (что я пытался, что не работает):
[DllImport("3RD_PARTY_API.dll")]
private static extern long SendRequest(ref string xData, int DataLen, int xTimeout);
Когда я вызываю метод SendRequest
в С#, я получаю стандартную обнаружена ошибка PInvokeStackImbalance от VS2010. Я думаю, что это проблема типов параметров, а не что-то вроде CharSet
или EntryPoint
в объявлении DllImport. Я действительно просто зациклился на том, как преобразовать *CString
в действительный тип С#.
Я нашел ответ. Хотелось бы, чтобы я по-прежнему работал с разработчиком, который написал этот код, чтобы я мог кричать на них. Они помещают оболочку вокруг API, так что метод, который я перечислял с тремя параметрами, затем вызывает фактический API без значения таймаута. Исключение PInvokeStackImbalance произошло из-за того, что я добавлял дополнительный параметр.
Вот настоящая процедура Clarion, а также правильный синтаксис С# для этого:
Clarion:
SendRequest Procedure(*CString xData, Long DataLen), Byte, Virtual
С#:
[DllImport("NOVA_API.dll", EntryPoint = "SendRequest")]
private static extern byte SendRequest(string xData, int DataLen);
В суммировании Clarion *CString
можно преобразовать в тип .NET string
в объявлениях DLLImport.
Большое спасибо тем, кто ответил. Вот дополнительный ресурс, который я использовал в моем поиске, который я нашел очень полезным: pinvoke.net
В С# a long
всегда 64 бит. long
в Clarion - 32 бита. Измените параметры long
в объявлении p/Invoke на int
.
В соответствии с wikipedia clarion может использоваться какой-то странный TopSpeed "двойной быстрый вызов", где они используют 4 регистра для параметров вместо двух. Если код скомпилирован с использованием этого соглашения о вызове, невозможно будет напрямую вызвать из С#.
TopSpeed /Clarion/JPI Первые четыре целочисленных параметра передаются в регистры eax, ebx, ecx и edx. Параметры плавающей точки передаются в стеке с плавающей запятой - регистры st0, st1, st2, st3, st4, st5 и st6. Параметры структуры всегда передаются в стек. Дополнительные параметры передаются в стек после того, как регистры исчерпаны. Целочисленные значения возвращаются в eax, указатели в edx и типах с плавающей запятой в st0.
Если это не так, вероятно, один из ваших параметров не является правильным размером, иначе вы получите AV вместо поврежденной ошибки стека.
Можно также попробовать установить соглашение о вызове в dllimport. Помимо "TOPSPEED", ядро также поддерживает stdcall и cdecl, но "TOPSPEED" по умолчанию. Ниже приведена ссылка на учебник по взаимодействию с vb6 и clarion.
CallingConvention
DllImport
атрибута CallingConvention.Cdecl
в CallingConvention.Cdecl
Вы пробовали char[]
? Я не уверен, что это сработает, но это того стоит. (Я бы опубликовал это как комментарий, но у меня нет прав)
LONG: A four-byte signed integer.
Не решил проблему, но я на шаг ближе ...