@VitaminPSG

Вызов функции Delphi из DLL написанной на C++?

Добрый день. Подскажите как правильно:
1) Передать из приложения написанного на Delphi указатель на функцию в DLL написанного на C++ ?
2) Вызывать функцию из DLL с передачей параметров и вернуть результат?

Ну собственно как я решал этот вопрос.

1. Описал типы функций.
TSendPacketStr = procedure (pck: string; const tid: integer; const ToServer: Boolean);stdcall;
  TGetConnectionName = function(id : integer):string;stdcall;
  TGetConnectioIdByName = function(name : string):integer;stdcall;
  PSendPacketStr = ^TSendPacketStr;
  PGetConnectionName = ^TGetConnectionName;
  PGetConnectioIdByName = ^TGetConnectioIdByName;

  TCFunctionStruct = record
  pSendPacketStr: PSendPacketStr;
  pGetConnectionName: PGetConnectionName;
  pGetConnectioIdByName: PGetConnectioIdByName;
  end;
  
  PCFunctionStruct = ^TCFunctionStruct;


2. Описал структуру функцию в которой буду передавать указатель в Delphi.
TSetCFStruct = function(const struct: PCFunctionStruct): Boolean; stdcall;


3. Создал переменную в которой буду хранить адрес функции.
SetCFStruct: TSetCFStruct;

4. Загружаю DLL. Нахожу адрес и записываю в переменную. А также передаю указатель на функцию.
@SetCFStruct:=GetProcAddress(hLib, 'SetFunctionStruct');
  if(Assigned(SetCFStruct)) then
  begin
      ScriptStruct.pSendPacketStr:=@TPluginStructClass.SendPacketStr;
      ScriptStruct.pGetConnectionName:=@TPluginStructClass.getConnectionName;
      ScriptStruct.pGetConnectioIdByName:=@TPluginStructClass.getConnectioidByName;
      SetCFStruct(@ScriptStruct);
  end;


5. Описываю структуру функций и функцию которые я буду принимать в DLL написанную на C++.
// Структура скриптов
struct ScriptStruct
{
	void(*sendPacketStr)(unsigned char* pck, const int tid, bool toServer);
	char*(*getConnectionName)(int);
	int(*getConnectioIdByName)(char* name);
};

/// Функция передачи указателя на ScriptStruct
DLL_API bool SetFunctionStruct(ScriptStruct * scriptStruct);


6. Далее в сpp пишу описание функци.
// Вызывается при включении плагина
DLL_API bool SetFunctionStruct(ScriptStruct * scriptStruct)
{
	OutputDebugStringA("SetFunctionStruct\n");
	_scriptStruct->getConnectionName(123); // <- Здесь я пытаюсь вызвать функцию из Delphi
	return true;
}


7. Запускаю проект через дебагер, подключаю DLL.
Мы приходим в точку останова функции
function TPluginStructClass.getConnectionName(id: integer): string; stdcall;
begin
  result := dmData.ConnectNameById(id); /// <- вызывается 
end;


После чего возникает креш.
  • Вопрос задан
  • 2401 просмотр
Пригласить эксперта
Ответы на вопрос 3
@raincons
Вы же в делфи функцию определили как stdcall, а в с - нет. Должно быть char* (__stdcall *getConnectionName)(int);
Ну и плюс сишный char* не равен делфевому string, char* будет PAnsiChar
Ответ написан
@vilgeforce
Раздолбай и программист
В Delphi другая конвенция вызовов, параметры функции в регистрах, а не на стеке. Плюс может быть другая работа со стеком. В C/C++ - stdcall если я не ошибаюсь, параметры строго на стеке. Вот и получается что-то не то. Правильно погуглить или не использовать Delphi, поскольку подводных камней может быть еще очень и очень много.
Ответ написан
Комментировать
Как минимум у Вас вызов getConnectionName() расходится в 1 параметре,
т.к. Вы его описали как function(id : integer):string; stdcall;
а присвоили указатель на function(id : integer):string of object; stdcall;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
CTRL+ Москва
от 250 000 до 320 000 ₽
CTRL+ Москва
от 200 000 до 300 000 ₽
CTRL+ Белград
от 250 000 до 320 000 ₽
22 нояб. 2024, в 02:56
10000 руб./за проект
22 нояб. 2024, в 00:55
500 руб./за проект
21 нояб. 2024, в 23:30
300000 руб./за проект