我一直在尝试根据这个documentation在delphi中重用一个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;
我已经阅读了geskill,Dan Hacker,max和Ron提出的类似问题,但它无法解决我的问题。
有人能告诉我这里有什么问题吗?
答案 0 :(得分:3)
我无法测试它,因为我没有libSQLDBC_C.dll
。
问题是already explained。作为您的案例的解决方法,您可以在Delphi ClientRuntime_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);
答案 1 :(得分: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
的可用性。这意味着你不能使用Delphi的SQLDBC_IRuntime
。
您需要创建一个C ++桥DLL,以Delphi可以调用的方式公开该功能。例如,通过公开调用SQLDBC_IRuntime
的C ++方法的普通旧函数。