Преобразование объявления процедуры Clarion в C # DLLImport

2

Как я могу преобразовать это объявление процедуры 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 в действительный тип С#.

Теги:
pinvoke
clarion

4 ответа

4
Лучший ответ

Я нашел ответ. Хотелось бы, чтобы я по-прежнему работал с разработчиком, который написал этот код, чтобы я мог кричать на них. Они помещают оболочку вокруг 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

3

В С# a long всегда 64 бит. long в Clarion - 32 бита. Измените параметры long в объявлении p/Invoke на int.

  • 0
    Хороший совет. Проверил помощь, и вы были правы. LONG: A four-byte signed integer. Не решил проблему, но я на шаг ближе ...
2

В соответствии с 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.

http://pisoft.ru/verstak/insider/cw_vb.htm

  • 0
    Я узнал, что DLL написана на C, но я ценю исследования. Я буду иметь это в виду на будущее. Теперь я уточнил это в своем вопросе: DLL написана на C, прототип в Clarion работает, но DLLImport в C # не работает.
  • 0
    Попробуйте установить CallingConvention DllImport атрибута CallingConvention.Cdecl в CallingConvention.Cdecl
1

Вы пробовали char[]? Я не уверен, что это сработает, но это того стоит. (Я бы опубликовал это как комментарий, но у меня нет прав)

  • 0
    Я попробовал это, но это не сработало. Спасибо за предложение. Я обновил свой вопрос соответственно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню