简体   繁体   中英

How to get interface from C dll to Delphi?

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;

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM