Reputation: 1
I have a library written in C and I have a header file with a description of the interface in C. The DLL has a function to get this interface. How to describe it correctly and get it in the DELPHI application?
using DllCallbackClassPtr = void*;
using DllCallbackFunction = void(*)(const char *, DllCallbackClassPtr);
#ifdef _WIN32
#include <Windows.h>
__interface IXeoma
{
public:
enum ConnectErrorCode {
OK = 0,
SERVER_NOT_FOUND,
WRONG_PASSWORD,
UNKNOWN
};
// return ConnectErrorCode
virtual int start(const char* connectionString) = 0;
virtual bool isConnected() = 0;
virtual void stop() = 0;
virtual void requestData(const char* request, const char* additionalData, DllCallbackClassPtr classPtr, DllCallbackFunction callbackFunc) = 0;
virtual const char* getRequestResult(const char* request) = 0;
virtual void setCameraRenderHandle(const char* previewId, HWND hWnd) = 0;
};
The library is loaded, but the function returns nil.
type
IXeoma = interface
function Start(connectionString: PChar): integer;
end;
type
TCreateXeomaInterface = function() : IXeoma; stdcall;
var
Form1: TForm1;
CreateXeomaInterface: TCreateXeomaInterface;
implementation
{$R *.dfm}
var
LibraryHandle: THandle;
procedure TForm1.Button1Click(Sender: TObject);
var
XeomaInt: IXeoma;
i: integer;
begin
LibraryHandle := LoadLibrary(PChar('D:\Projects\XeomaSDK\Win32\Debug\xeomaclientdll.dll'));
if LibraryHandle >= 32 then
begin
@CreateXeomaInterface := GetProcAddress(LibraryHandle, 'createXeomaInterface');
end;
XeomaInt := CreateXeomaInterface();
// Here XeomaInt = nil
end;
Upvotes: 0
Views: 351
Reputation: 595339
The __interface
extension in Visual C++, and the interface
keyword in Delphi, are not the same thing, and are not compatible with each other.
IXeoma
in the C++ code is just an ordinary class type, not a COM interface. But in Delphi, all interface
s derive from IUnknown
, and all class
es derive from TObject
, neither of which you want in this situation. So, you are going to have to use a plain record
instead, and declare TCreateXeomaInterface
as returning a pointer to that record.
Also, note that a Delphi record
can't have virtual
methods, but the C++ class does have them, so you are going to have to manually account for the C++ class's vtable in Delphi.
Try something like this:
type
DllCallbackClassPtr = Pointer;
DllCallbackFunction = procedure(Param1: PAnsiChar; Param2: DllCallbackClassPtr); cdecl;
IXeomaPtr = ^IXeoma;
IXeomaVTable = record
start: function(_Self: IXeomaPtr; connectionString: PAnsiChar): Integer; cdecl;
isConnected: function(_Self: IXeomaPtr): Boolean; cdecl;;
stop: procedure(_Self: IXeomaPtr); cdecl;
requestData: procedure(_Self: IXeomaPtr; request: PAnsiChar; additionalData: PAnsiChar; classPtr: DllCallbackClassPtr; callbackFunc: DllCallbackFunction); cdecl;
getRequestResult: function(_Self: IXeomaPtr; request: PAnsiChar): PAnsiChar; cdecl;
setCameraRenderHandle: procedure(_Self: IXeomaPtr; previewId: PAnsiChar; hWnd: HWND); cdecl;
end;
ConnectErrorCode = (
OK = 0,
SERVER_NOT_FOUND,
WRONG_PASSWORD,
UNKNOWN
);
IXeoma = record
vtable: ^IXeomaVTable:
end;
type
TCreateXeomaInterface = function() : IXeomaPtr; stdcall;
var
Form1: TForm1;
CreateXeomaInterface: TCreateXeomaInterface;
implementation
{$R *.dfm}
var
LibraryHandle: THandle;
procedure TForm1.Button1Click(Sender: TObject);
var
XeomaInt: IXeomaPtr;
i: integer;
begin
XeomaInt := nil;
LibraryHandle := LoadLibrary('D:\Projects\XeomaSDK\Win32\Debug\xeomaclientdll.dll');
if LibraryHandle >= 32 then
begin
@CreateXeomaInterface := GetProcAddress(LibraryHandle, 'createXeomaInterface');
XeomaInt := CreateXeomaInterface();
if XeomaInt <> nil then
XeomaInt^.vtable^.start(XeomaInt, '123:123@localhost:8090');
end;
...
end;
Upvotes: 3