Вызов функции DLL Delphi из кода C # - PullRequest
7 голосов
/ 28 декабря 2011

У меня есть DLL, скомпилированная в Delphi 2007, и пример использования ее в другом проекте Delphi. Вот часть кода:

TErrorCallback = function(Msg:PChar):byte of object;
TSaveEventCallback = function (Line:PChar; HiCode:PChar; LoCode:PChar; MobileNo:PChar):byte of object;

function InitModule(ErrorCallback:TErrorCallback; SaveEventCallback :TSaveEventCallback; MainWindowHandle:THandle; Sock_Event:integer):byte; stdcall; external 'My.dll' name 'InitModule';

function DLLSocketEvent(var msg: TMessage): byte; stdcall; external 'My.dll' name 'DLLSocketEvent';

function InitObjList(Objs: array of PChar; NumObjs: byte; Name: PChar):byte; stdcall; external 'My.dll' name 'InitObjList';

А вот мой аналог C #:

class Message
{
  unsigned int msg;
  int wParam;
  int lParam;
  int result;
};
delegate byte ErrorCallbackDelegate(string msg);
delegate byte SaveEventCallbackDelegate(string line, string hiCode, string loCode, string mobileNo);

[DllImport("My.dll")]
static extern byte InitModule(ErrorCallbackDelegate errorCallback, SaveEventCallbackDelegate saveEventCallback, IntPtr mainWindowsHandle, Int32 sockEvent);

[DllImport("My.dll")]
static extern byte DllSocketEvent(Message msg);

[DllImport("My.dll")]
static extern byte InitObjList(string[] objs, byte numObjs, string name);

Дело в том, что я пробовал только метод InitModule, и он выдал исключение: Вызов функции PInvoke «ProjTest! ProjTest.MyClass :: InitModule» разбалансирует стек. Это вероятно потому, что управляемая подпись PInvoke не совпадает с неуправляемой целевой подписью. Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

Пожалуйста, помогите мне с этим. Как я должен описать эти функции DLL в C #?

1 Ответ

11 голосов
/ 28 декабря 2011

Вы не можете вызвать эту DLL из C #.Основная проблема - два обратных вызова of object.В C # нет способа соответствовать этому.Вам нужно будет изменить существующую DLL или добавить промежуточный адаптер DLL.В настоящее время ваша DLL доступна только из Delphi или C ++ Builder.

Если вы можете изменить DLL, то вам нужно будет удалить of object.Если вам нужен обратный вызов для работы с экземпляром, вам нужно будет передать экземпляр в качестве параметра.Тем не менее, делегаты C # могут прозрачно обернуть все это, так что вам нужно будет только передать экземпляр в качестве параметра, если вы хотите, чтобы DLL была доступна из других языков, например Delphi.

Другая проблема - открытый массивпараметр.Это также не легко получить доступ с других языков.Хотя есть трюки , я бы рекомендовал передавать ссылку на первый элемент, а не открытый массив.Открытые массивы уникальны для Delphi.

Я также не понимаю, почему вы используете тип byte для хранения длины массива.Вы должны использовать Integer для этого.Использование байта ничего не дает, и вы просто приглашаете переполнение.Кроме того, MainWindowHandle не должно быть THandle в Delphi.Это должно быть HWND.

Я бы порекомендовал вам изменить библиотеку DLL, чтобы иметь интерфейс, совместимый с C, и, таким образом, он был доступен со всех языков, которые это поддерживают.На практике это сделает его доступным для всех основных языков программирования.

...