Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在delphi中使用C-dll不返回任何内容_Delphi_Dll_Dllimport - Fatal编程技术网

在delphi中使用C-dll不返回任何内容

在delphi中使用C-dll不返回任何内容,delphi,dll,dllimport,Delphi,Dll,Dllimport,基于此,我一直在尝试在delphi中重用C dll文件 服务器运行良好,我可以访问并使用本地服务器上的数据库 java和php 在delphi上,我使用动态加载,在所有返回变量的函数上都工作得很好,但在返回接口的函数上却失败了 unit for library : unit SQLDBC_C; interface uses windows, classes, sysutils; type SQLDBC_IRuntime = interface end; var getSDKVe

基于此,我一直在尝试在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;
我已经读过类似的问题,但它不能解决我的问题


有人能告诉我这里出了什么问题吗?

我无法测试它,因为我没有
libSQLDBC\u C.dll

问题是。作为案例的解决方法,您可以在Delphi
ClientRuntime\u GetClientRuntime
声明中返回指针

ClientRuntime_GetClientRuntime: function (errorText:Pchar;
                                errorTextSize:Integer): Pointer; stdcall;
并将其转换到
SQLDBC\u IRuntime
界面:

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

begin
  Pointer(rt):= ClientRuntime_GetClientRuntime(@err,200); 

我无法测试它,因为我没有
libSQLDBC_C.dll

问题是。作为案例的解决方法,您可以在Delphi
ClientRuntime\u GetClientRuntime
声明中返回指针

ClientRuntime_GetClientRuntime: function (errorText:Pchar;
                                errorTextSize:Integer): Pointer; stdcall;
并将其转换到
SQLDBC\u IRuntime
界面:

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

begin
  Pointer(rt):= ClientRuntime_GetClientRuntime(@err,200); 

返回接口的C++函数不容易映射到Delphi函数。Delphi中托管类型返回值的调用约定与C++所使用的不匹配。p>

说明,我创建了一个简单的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';
var
  intf: IUnknown;
....
Pointer(intf) := GetInterface;
然而,当我们调用此函数时,它总是返回
nil

解决方案完全符合Serg的建议:

function GetInterface: Pointer; stdcall; external DLL name '_GetInterface@0';
我们可以这样称呼它:

function GetInterface: IUnknown; stdcall; external DLL name '_GetInterface@0';
var
  intf: IUnknown;
....
Pointer(intf) := GetInterface;
当我们这样做时,
intf
不是
nil
,我们可以非常愉快地调用它的方法

因此,我们在这里学到的是,Delphi无法轻松调用返回接口的外部函数,除非这些外部函数也在Delphi中实现。但至少我们有一个可行的解决办法


不幸的是,这种变通方法对您没有直接的用处。这是因为<代码> SqLDbcIrunTime/Cux>是C++类。它不是COM兼容的接口。请注意,
SQLDBC\u IRuntime
没有实现
IInterface
。因此它不提供
\u AddRef
\u Release
查询接口
。Delphi的接口支持取决于
IInterface
的可用性。这意味着您不能使用Delphi中的
SQLDBC\u IRuntime


您需要制作一个C++ DLL,它以Delphi调用的方式公开功能。例如,通过公开调用C++方法的普通旧函数,即代码> SqLDbcIrIunTime//>代码>

< P>一个返回接口的C++函数不容易映射到Delphi函数。Delphi中托管类型返回值的调用约定与C++所使用的不匹配。p>

说明,我创建了一个简单的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';
var
  intf: IUnknown;
....
Pointer(intf) := GetInterface;
然而,当我们调用此函数时,它总是返回
nil

解决方案完全符合Serg的建议:

function GetInterface: Pointer; stdcall; external DLL name '_GetInterface@0';
我们可以这样称呼它:

function GetInterface: IUnknown; stdcall; external DLL name '_GetInterface@0';
var
  intf: IUnknown;
....
Pointer(intf) := GetInterface;
当我们这样做时,
intf
不是
nil
,我们可以非常愉快地调用它的方法

因此,我们在这里学到的是,Delphi无法轻松调用返回接口的外部函数,除非这些外部函数也在Delphi中实现。但至少我们有一个可行的解决办法


不幸的是,这种变通方法对您没有直接的用处。这是因为<代码> SqLDbcIrunTime/Cux>是C++类。它不是COM兼容的接口。请注意,
SQLDBC\u IRuntime
没有实现
IInterface
。因此它不提供
\u AddRef
\u Release
查询接口
。Delphi的接口支持取决于
IInterface
的可用性。这意味着您不能使用Delphi中的
SQLDBC\u IRuntime


您需要制作一个C++ DLL,它以Delphi调用的方式公开功能。例如,公开了调用C++代码方法的普通旧函数,即DLDPHI的哪个版本?你确定是stdcall吗?很有可能是cdecl。这让我想起了这个问题:@DavidHeffernan谢谢你的回答。stdcall和cdecl之间没有区别。我在Windows XP机器上,正在尝试Delphi 6、7和XE2。请确保使用AnsiChar for XE2。最好在这个库中始终使用它。尝试C++程序并检查它是否有效。如果是,有什么不同?这就是问题所在。它在C++、java和PHP上都有很好的应用。在Delphi6、7和XE2上,库成功地加载了返回字符串和数值的函数,但返回接口的所有函数除外。如果我使用接口,它将返回nil。如果我使用指针,它返回指针但抛出异常。哪个版本的Delphi?你确定是stdcall吗?很有可能是cdecl。这让我想起了这个问题:@DavidHeffernan谢谢你的回答。stdcall和cdecl之间没有区别。我在Windows XP机器上,正在尝试Delphi 6、7和XE2。请确保使用AnsiChar for XE2。最好在这个库中始终使用它。尝试C++程序并检查它是否有效。如果是,有什么不同?这就是问题所在。它在C++、java和PHP上都有很好的应用。在Delphi6、7和XE2上,库成功地加载了返回字符串和数值的函数,但返回接口的所有函数除外。如果我使用接口,它将返回nil。若我使用指针,它返回指针,但抛出异常;Delphi原型错误,因此返回值不会显示为函数的结果。@Serg您能详细说明一下吗?我想你的问题链接不适用于这里。有许多Win32 API函数返回COM接口,因此。我的直觉是问题在于

SQLDBC\u IRuntime
根本不是一个COM