本人想使用Delphi制作一个Dll,然后在VB中使用它,我只是测试一下,在Delphi中New->Dll,然后就build了,什么都没有做,然后在到vb中引用它(DLL),结果vb不幸报错:“不能将引用加入指定文件”,各位帮我看看,我该怎么办呀?谢谢!
(我需要在delphi中作一些工作,再到vb中调用的。)
(我需要在delphi中作一些工作,再到vb中调用的。)
解决方案 »
- 怎么检测 键盘 鼠标 是PS/2 还是USB的?
- 3层,,自己做的接口怎么把数据回传到客户端呢?
- 一个存储过程的小问题?
- 一个 简单的问题
- fastReport
- 一个特容易得分的问题:请告诉我“~”(键盘上1左边的键,像波浪一样的符号)的常数是多少?
- 在写一份英文简历,每个项目下面都要些段很长的项目描述Description,共写八个项目,应该每个描述都不同才好,但不知道该怎么写这种描述
- quickreport中分组统计如何打?
- 如何用DELPHI执行网页表单的按妞呢?在线等!
- 怎么对网页进行分析,如只取出一部分表格中的文字?
- 三个很菜但对我很重要的问题
- ????关于自动填写网页的一个小问题!!在线等待…………
Delphi中高级DLL的编写和调用
2001年06月14日10:54:38 赛迪网 苏涌根据Delphi提供的有关 DLL编写和调用的帮助信息,你可以很快完成一般的 DLL编写和
调用的 应用程序。本文介绍的主题是如何编写和调用能够传递各种参数(包括对象实例
)的 DLL。例如, 主叫程序传递给 DLL一个ADOConnection 对象示例作为参数, DLL中
的函数和过程调用通过该对象 实例访问数据库。需要明确一些基本概念。对于 DLL,需要在主程序中包含 exports子句,用于向外界提
供调用 接口,子句中就是一系列函数或过程的名字。对于主叫方(调用 DLL的应用程序
或其它的 DLL), 则需要在调用之前进行外部声明,即external保留字指示的声明。这
些是编写 DLL和调用 DLL必须 具备的要素。另外需要了解Object Pascal 中有关调用协议的内容。在Object Pascal 中,对于过程
和函数 有以下五种调用协议:指示字 参数传递顺序 参数清除者 参数是否使用寄存器
register 自左向右 被调例程 是
pascal 自左向右 被调例程 否
cdecl 自右向左 调用者 否
stdcall 自右向左 被调例程 否
safecall 自右向左 被调例程 否 这里的指示字就是在声明函数或过程时附加在例程标题之后的保留字,默认为register,
即是 唯一使用 CPU寄存器的参数传递方式,也是传递速度最快的方式;pascal: 调用协议仅用于向后兼容,即向旧的版本兼容;
cdecl: 多用于 C和 C++语言编写的例程,也用于需要由调用者清除参数的例程;
stdcall: 和safecall主要用于调用Windows API 函数;其中safecall还用于双重接口。
在本例中,将使用调用协议cdecl ,因为被调用的 DLL中,使用的数据库连接是由主叫方
传递 得到的,并且需要由主叫方处理连接的关闭和销毁。下面是 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;interfaceuses
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;interfaceuses
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 在File菜单中的New里面选择Dll Wizard
然后,就是调用Dll,调用Dll的方法有两种:静态调用和动态调用
静态调用的方法:
首先,申明(说明SetBillModule是动态连接库billSet.dll的接口函数)
procedure SetBillModule(AOwner: TWinControl;db: TIBDatabase;Params: shortstring; PCallBackFunc: Pointer); external 'E:\billSet.dll'
然后,在程序中调用SetBillModule
动态调用的方法:(说明:RunFlowSet是FlowSet.dll的接口函数)
procedure TForm1.Button1Click(Sender: TObject);
type
a = procedure (AOwner: TWinControl;db: TIBDatabase;Params: shortstring; PCallBackFunc: Pointer);
var
hdll,ahdll: THandle;
pf: Pointer;
begin
Form2 := TForm2.Create(nil);
hdll := LoadLibrary('E:\FlowSet.dll');
if hdll = 0 then
begin
showmessage('无法加载');
Screen.Cursor := crDefault;
Exit;
end;
pf := GetProcAddress(hdll,'RunFlowSet');
a(pf)(Form2.Panel1,IBDatabase1,inttostr(ahDll),nil);
Form2.Show;
end; 资源dll的用法:
1、编辑*.rc文件内容类似下面的ActiveLeftTop BITMAP "ActiveLeftTop256.bmp"
ActiveMenubar BITMAP "ActiveMenubar256.bmp"
ActiveRightTop BITMAP "ActiveRightTop256.bmp"
ActiveTop BITMAP "ActiveTop256.bmp"
Bottom BITMAP "Bottom256.bmp"
Close BITMAP "Close256.bmp"
......
2、运行 brcc32 -fo1.res -32 1.rc
1.rc 1.res为文件名
3、新建dll工程,添加上面的资源文件,编译生成test.dll文件library test;
uses
SysUtils,
Classes;{$R 1.RES} //加上这一句begin
end.4、在你的程序中用下面的方法使用:
var h:THandle;
bmp:TBitmap;
begin
h:=LoadLibrary('test');
if h<=0 then
showMessage('Load Dll Error')
else begin
bmp:=TBitMap.Create;
bmp.Handle:=loadBitmap(h,'ActiveTop');
Image1.Picture.Bitmap.Assign(bmp);
canvas.Draw(0,0,bmp);
bmp.Free;
freeLibrary(h);
end;end; 可以把任意文件放入
下面我给你一个放入Exe文件的例子,任意都是一样的
RC文件中是
nestexe exefile "c:\nestexe.exe"
程序里面是
{$R nestexe.res}procedure TForm1.btnStartClick(Sender: TObject);
var
ResHandle : THandle;
MemHandle : THandle;
MemStream : TMemoryStream;
ResPtr : PByte;
ResSize : Longint;
F: TFileStream;
begin
F := TFileStream.Create('d:\aa.exe',fmCreate);
ResHandle := FindResource(hInstance, PChar('nestexe'), 'exefile');
MemHandle := LoadResource(hInstance, ResHandle);
ResPtr := LockResource(MemHandle);
MemStream := TMemoryStream.Create;
ResSize := SizeOfResource(hInstance, ResHandle);
MemStream.SetSize(ResSize);
MemStream.Write(ResPtr^, ResSize);
FreeResource(MemHandle);
MemStream.Seek(0, 0);
F.CopyFrom(MemStream,MemStream.Size);
F.Free;
//
MemStream.Free;
end;
project单元:
library ColorFrm;uses
SysUtils,
Classes,
FrmColor in 'FrmColor.pas' {ColorForm};exports
FBColor;{$R *.res}begin
end.
unit FrmColor;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ColorGrd;type
TColorForm = class(TForm)
ColorGrid1: TColorGrid;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
ColorForm: TColorForm;Function FBColor(Var FColor,BColor:Tcolor):WordBool;export;implementation{$R *.dfm}procedure TColorForm.BitBtn1Click(Sender: TObject);
begin
ModalResult:=mrOK;
end;procedure TColorForm.BitBtn2Click(Sender: TObject);
begin
ModalResult:=mrCancel;
end;Function FBColor(Var FColor,BColor:TColor):WordBool;
begin
Result:=False;
ColorForm:=TColorForm.Create(Application);
try
if ColorForm.ShowModal=mrOK then
with ColorForm do
begin
FColor:=ColorGrid1.ForegroundColor;
BColor:=ColorGrid1.BackgroundColor;
Result:=True;
end;
finally
ColorForm.Free;
end;
end;end.