1

このドキュメントに基づいて、デルファイでC dllファイルを再利用しようとしています。

サーバーは正常に動作していました。Java と php を使用して、ローカル サーバー上のデータベースにアクセスして使用することができました。

Delphiでは、動的ロードを使用し、変数を返すすべての関数でうまく機能しましたが、インターフェイスを返す関数では失敗しました。

unit for library :
unit SQLDBC_C;

interface
uses windows, classes, sysutils;

type
  SQLDBC_IRuntime = interface
  end;

var
  getSDKVersion : function :Pchar; stdcall;
  ClientRuntime_GetClientRuntime: function (errorText:Pchar; errorTextSize:Integer) : SQLDBC_IRuntime; stdcall;

implementation

var
  libhandle : THandle;

procedure initLibrary;
begin
  libhandle := LoadLibrary('libSQLDBC_C.dll');
  if libhandle>=23 then begin
     @getSDKVersion:=GetProcAddress(libhandle,'getSDKVersion');
     @ClientRuntime_GetClientRuntime:=
        GetProcAddress(libhandle,'ClientRuntime_GetClientRuntime');
  end;
end;

initialization
begin
  initLibrary;
end;

finalization
begin
  if libhandle>=32 then
    FreeLibrary(libhandle);
end;

end.

テスト手順は次のとおりです。

procedure TForm1.Button1Click(Sender: TObject);
var
  err : array [0..200] of char;
  rt : SQLDBC_IRuntime;

begin
  Memo1.Clear;
  FillChar(err, sizeof(err), 0);
  Memo1.Lines.Add(getSDKVersion); //this function successed

  rt := ClientRuntime_GetClientRuntime(@err,200); 
  //this function had no return value, (rt always nil) but no error return at err variable
  if assigned(rt) then begin
    ......
  end;
end;

geskillDan Hackermax、およびRonによって尋ねられた同様の問題を読みましたが、私の問題を解決できませんでした。

ここで何が悪いのか誰か教えてもらえますか?

4

2 に答える 2

3

インターフェイスを返す C++ 関数は、Delphi 関数に簡単にマップできません。Delphi で管理されている型である戻り値の呼び出し規約は、C++ で使用されているものと一致しません。

説明のために、この関数をエクスポートする単純な C++ テスト DLL を作成しました。

extern "C" __declspec(dllexport) IUnknown* __stdcall GetInterface()
{
    CoInitialize(NULL);
    IUnknown* result;
    CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, 
      IID_IUnknown, (void**) &result);
    return result;
}

これを Delphi にマッピングする明白な方法は次のとおりです。

function GetInterface: IUnknown; stdcall; external DLL name '_GetInterface@0';

ただし、この関数を呼び出すと、常に が返されますnil

回避策は、Serg が提案したとおりです。

function GetInterface: Pointer; stdcall; external DLL name '_GetInterface@0';

そして、次のように呼び出すことができます。

var
  intf: IUnknown;
....
Pointer(intf) := GetInterface;

これを行うと、そうでintfはなくnil、メソッドを非常にうまく呼び出すことができます。

したがって、ここで学んだことは、Delphi はインターフェイスを返す外部関数を簡単に呼び出すことができないということです。これらの外部関数も Delphi で実装されている場合を除きます。しかし、少なくとも実行可能な回避策があります。


残念ながら、この回避策はすぐには役に立ちません。それ SQLDBC_IRuntimeは C++ クラスだからです。COM 互換インターフェイスではありません。SQLDBC_IRuntimeを実装していないことに注意してくださいIInterface_AddRefしたがって、 、_Releaseおよびは提供されませんQueryInterface。Delphi のインターフェイス サポートは、IInterface. SQLDBC_IRuntimeこれは、Delphi からは使用できないことを意味します。

Delphi が呼び出すことができる方法で機能を公開する C++ ブリッジ DLL を作成する必要があります。たとえば、SQLDBC_IRuntime.

于 2012-09-29T08:08:41.870 に答える
3

持っていないのでテストできませんlibSQLDBC_C.dll

問題はすでに説明されています。あなたのケースの回避策として、DelphiClientRuntime_GetClientRuntime宣言でポインタを返すことができます

ClientRuntime_GetClientRuntime: function (errorText:Pchar;
                                errorTextSize:Integer): Pointer; stdcall;

SQLDBC_IRuntimeそしてそれをインターフェースにキャストします:

var
  err : array [0..200] of char;
  rt : SQLDBC_IRuntime;

begin
  Pointer(rt):= ClientRuntime_GetClientRuntime(@err,200); 
于 2012-09-29T04:45:52.487 に答える