Reputation: 31
I have a simple program that exports a DLL, this DLL exports functions from another DLL:
// SDK_DLL.cpp :
#include "functions.h"
#include "functions_advanced.h"
#include "stdafx.h"
#include <stdio.h>
using namespace std;
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL...");
}
__declspec(dllexport) function_config FuncInit = appd_config_init();
__declspec(dllexport) function_config * FuncInit2()
{
function_config* cfg = function_config_init();
return cfg;
}
}
The function_config_init() returns a pointer, I cannot seem to find a way of making this proper export declaration.
I am loading a simple function to Delphi this way:
procedure DisplayHelloFromDLL; external 'C:\Users\Administrator\Documents\Visual Studio 2017\Projects\SDK_DLL\Debug\SDK_DLL.dll';
Will I need to change the way I am loading this pointer returning function?
Thanks a lot for your help.
Upvotes: 0
Views: 224
Reputation: 598011
FuncInit
is an exported variable. Delphi does not support importing of variables via external
, only of functions. If you need to import FuncInit
, you will have to use GetProcAddress()
directly to get a pointer to the variable at runtime:
type
// you did not show the C/C++ declaration
// of function_config, so I can't provide
// a translation here, but it is likely to
// be a struct, which is a record in Delphi ...
function_config = ...;
pfunction_config = ^function_config;
function GetFuncInit: pfunction_config;
begin
Result := pfunction_config(GetProcAddress(GetModuleHandle('SDK_DLL.dll'), 'FuncInit'));
end;
var
FuncInit: pfunction_config;
FuncInit := GetFuncInit;
For purposes of interop across languages/compilers, the only portable calling conventions are cdecl
and stdcall
. When no calling convention is specified in code, the default used by most C and C++ compilers is __cdecl
(but can usually be specified in compiler settings), while the default used by Delphi is register
instead (__fastcall
in C++Builder).
When no parameters or return value are used, like in DisplayHelloFromDLL()
, then declaring the wrong calling convention does not really matter. But when parameters and/or a return value are used, like in FuncInit2()
, then declaring the correct calling convention matters. See Pitfalls of converting for more details.
So, the two DLL functions in question would likely need to be declared like the following in Delphi:
type
function_config = ...;
pfunction_config = ^function_config;
procedure DisplayHelloFromDLL; cdecl; external 'SDK_DLL.dll' name '_DisplayHelloFromDLL';
function FuncInit2: pfunction_config; cdecl; external 'SDK_DLL.dll' name '_FuncInit2';
If the DLL uses a .def
file to remove name mangling from the exported names, you can omit the name
attribute:
type
function_config = ...;
pfunction_config = ^function_config;
procedure DisplayHelloFromDLL; cdecl; external 'SDK_DLL.dll';
function FuncInit2: pfunction_config; cdecl; external 'SDK_DLL.dll';
Upvotes: 2