S
S
Sergey2015-09-15 10:40:07
Delphi
Sergey, 2015-09-15 10:40:07

Calling a Delphi function from a C++ DLL?

Good afternoon. Prompt as correctly:
1) To transfer from the application written on Delphi the pointer on function in DLL written on C ++?
2) Call a function from a DLL with parameter passing and return the result?
Well, actually how I solved this issue.
1. Described the types of functions.

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. Described the structure of the function in which I will pass the pointer to Delphi.
TSetCFStruct = function(const struct: PCFunctionStruct): Boolean; stdcall;

3. I created a variable in which I will store the address of the function.
SetCFStruct: TSetCFStruct;
4. I load the DLL. I find the address and write it to a variable. I also pass a pointer to the function.
@SetCFStruct:=GetProcAddress(hLib, 'SetFunctionStruct');
  if(Assigned(SetCFStruct)) then
  begin
      ScriptStruct.pSendPacketStr:[email protected];
      ScriptStruct.pGetConnectionName:[email protected];
      ScriptStruct.pGetConnectioIdByName:[email protected];
      SetCFStruct(@ScriptStruct);
  end;

5. I describe the structure of functions and the function that I will take in a DLL written in 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. Next, in cpp I write a description of the function.
// Вызывается при включении плагина
DLL_API bool SetFunctionStruct(ScriptStruct * scriptStruct)
{
  OutputDebugStringA("SetFunctionStruct\n");
  _scriptStruct->getConnectionName(123); // <- Здесь я пытаюсь вызвать функцию из Delphi
  return true;
}

7. I launch the project through the debugger, I connect the DLL.
We arrive at a function breakpoint
function TPluginStructClass.getConnectionName(id: integer): string; stdcall;
begin
  result := dmData.ConnectNameById(id); /// <- вызывается 
end;

Then there is a crash.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
R
Rainbird, 2015-09-15
@Rainberd

You defined the function as stdcall in delphi, but not in c. It should be char* (__stdcall *getConnectionName)(int);
Well, plus the sish char* is not equal to the Delphi string, char* will be PAnsiChar

V
Vladimir Martyanov, 2015-09-15
@vilgeforce

Delphi has a different calling convention, function parameters are in registers, not on the stack. Plus, there may be other work with the stack. In C / C ++ - stdcall, if I'm not mistaken, the parameters are strictly on the stack. This is where something goes wrong. It is correct to google or not to use Delphi, since there can still be a lot of pitfalls.

A
Andrew, 2015-09-15
@OLS

At least your call to getConnectionName() diverges in 1 parameter,
because You described it as function(id : integer):string; stdcall;
and assigned a pointer to function(id : integer):string of object; stdcall;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question