DLL调用问题

hhycqrm01 2005-10-17 09:19:57
我用DELPHI中调用一个DLL文件里面的函数时。出现了地址错误。请问各位大虾是怎么回事。我想了好几天了,都没有想通。也问过很多人。
...全文
210 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
jasengod2003 2005-10-19
  • 打赏
  • 举报
回复
下面是 DLL完整源程序和主叫程序完整源程序。包括以下四个文件:

Project1.DPR {主叫程序}
Unit1.PAS {主叫程序单元}
Project2.DPR {DLL}
Unit2.PAS {DLL单元}


{---------- DLL 主程序 Project2.DPR ----------}

library Project2;

uses
SysUtils,
Classes,
Unit2 in 'Unit2.pas' {Form1};

{$R *.RES}

{ 下面的语句用于向调用该 DLL的程序提供调用接口 }
exports
DoTest; { 过程来自单元Unit2 }

begin
end.


{---------- DLL中的单元 Unit2.PAS ----------}

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, ADODB, StdCtrls, Menus;

type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;{ 本地数据库连接 }
Memo1: TMemo; { 用于显示信息 }
private
public
end;

{ 该过程向外提供 }
procedure DoTest(H: THandle; { 获得调用者的句柄 }
AConn: TADOConnection;{ 获得调用者的数据库连接 }
S: string; { 获得一些文本信息 }
N: Integer); { 获得一些数值信息 }
cdecl; { 指定调用协议 }

implementation

{$R *.DFM}

procedure DoTest(H: THandle; AConn: TADOConnection; S: string; N: Integer);
begin
Application.Handle := H; { 将过程的句柄赋值为调用者的句柄 }
{ 上面语句的作用在于, DLL的句柄和调用者的句柄相同,在任务栏中就不会 }
{ 各自出现一个任务标题了。 }
with TForm1.Create(Application) do try{ 创建窗体 }
Memo1.Lines.Append('成功调用'); { 显示一行信息 }
ADOConnection1 := AConn; { 获得数据库连接的实例 }
Memo1.Lines.Append(
ADOConnection1.ConnectionString +
' - ' + S + ' - ' + IntToStr(N)); { 根据得到的参数显示另一行信息 }
ShowModal; { 模式化显示窗体 }
finally
Free; { 调用结束时销毁窗口 }
end;
end;

end.


{---------- 调用者 Project1.DPR,很普通的工程文件 ----------}

program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.


{---------- 调用者单元Unit1.PAS ----------}

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Db, ADODB;

type
TForm1 = class(TForm)
Button1: TButton; { 按此按钮进行调用 }
ADOConnection1: TADOConnection; { 本地数据库连接,将传递给 DLL }
procedure Button1Click(Sender: TObject);{ 调用 DLL}
private
public
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

{ 外部声明必须和 DLL中的参数列表一致,否则会运行时错误 }
procedure DoTest(H: THandle; { 传递句柄 }
AConn: TADOConnection; { 传递数据库连接 }
S: string; { 传递文本信息 }
N: Integer); { 传递数值信息 }
cdecl; { 指定调用协议 }
external 'Project2.dll';{ 指定过程来源 }

{ 调用过程 }
procedure TForm1.Button1Click(Sender: TObject);
begin
DoTest(Application.Handle,
ADOConnection1,
'Call OK',
256);
end;

end.
hhycqrm01 2005-10-19
  • 打赏
  • 举报
回复
用的C++开发的。
hhycqrm01 2005-10-19
  • 打赏
  • 举报
回复
type strout=packed record
errtxet:pchar;
out:pchar;
end;
var
mystrout:strout;
function getybjgbm:strout;stdcall; external 'CxybClient.dll';
function reg(ybjgbm,yybm,bz,czymc,scrj,sftsmz:pchar):strout;stdcall;external 'CxybClient.dll';
调用:
mystrout:=getybjgbm;
mystrout:=reg('100001','1000010001','0',pchar(frmlogin.name),pchar(formatdatetime('yyyy-mm-dd',frmmain.MyDate)),'0');

还是会出现同样的错误!!
小呆之家 2005-10-19
  • 打赏
  • 举报
回复
//---下面应当定义一个指针;
//---对了,结构体中的string类型也最好是用pchar类型。
type
strout=^StroutBlock//---
StroutBlock =packed record
//errtxet: string;
//out1: String;
errtxet: pchar;
out1: pchar;
end;
小呆之家 2005-10-19
  • 打赏
  • 举报
回复
前面我定义了一个结构体:
//---DLL开发语言是C++
//---第一个函数返回的是动态分配内存的入口地址吧
//---下面应当定义一个指针;
type
strout=^StroutBlock//---
StroutBlock =packed record
errtxet: string;
out1: String;
end;

var
mystrout:strout;
定义:
function getybjgbm:strout;stdcall; external 'CxybClient.dll';
//-----在C++中不存在String类型数据吧,应当是*char,在D中对应为Pchar;
//function reg(ybjgbm,yybm,bz,czymc,scrj,sftsmz:string):strout;stdcall;
function reg(ybjgbm,yybm,bz,czymc,scrj,sftsmz:pchar):strout;stdcall;
external 'CxybClient.dll';
调用:
mystrout:=getybjgbm;
mystrout:=reg('100001','1000010001','0',pchar(frmlogin.name),pchar(formatdatetime('yyyy-mm-dd',frmmain.MyDate)),'0');


你这样试试吧,我感觉这两个函数返回的都是一个结构体地址有些怪。呵~~。估计你是在第一个函数执行后,分配了内存,在DLL中也保存了这个入口地址,第二个函数操作这块内存后,将结果集再用指针返回到调用者程序中。
hhycqrm01 2005-10-17
  • 打赏
  • 举报
回复
前面我定义了一个结构体:

type Strout =packed record
errtxet: string;
out1: String;
end;

var
mystrout:strout;
定义:
function getybjgbm:strout;stdcall; external 'CxybClient.dll';
function reg(ybjgbm,yybm,bz,czymc,scrj,sftsmz:string):strout;stdcall; external 'CxybClient.dll';
调用:
mystrout:=getybjgbm;
mystrout:=reg('100001','1000010001','0',frmlogin.name,formatdatetime('yyyy-mm-dd',frmmain.MyDate),'0');
mastersky 2005-10-17
  • 打赏
  • 举报
回复
楼主的问题不要这么抽象。
小呆之家 2005-10-17
  • 打赏
  • 举报
回复
你要把你的DLL函数原型发上来,把你的调用代码发上来。要不,我是想不出你
有什么不对的地方滴。呵~~
小呆之家 2005-10-17
  • 打赏
  • 举报
回复
你的DLL是什么语言开发的?
我感觉你要利用数据结构的话,你应当在你的函数中用指针参数来传入内存块入口
地址啊。

5,379

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧