使用Delphi制作DLL文件使用的问题,散分了!!!

lhh 2003-07-10 03:09:04
本人想使用Delphi制作一个Dll,然后在VB中使用它,我只是测试一下,在Delphi中New->Dll,然后就build了,什么都没有做,然后在到vb中引用它(DLL),结果vb不幸报错:“不能将引用加入指定文件”,各位帮我看看,我该怎么办呀?谢谢!
(我需要在delphi中作一些工作,再到vb中调用的。)
...全文
87 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
雨后阳光2000 2003-07-10
  • 打赏
  • 举报
回复
对,dll要有一个接口(函数)。才能被别的程序引用。
project单元:
library ColorFrm;

uses
SysUtils,
Classes,
FrmColor in 'FrmColor.pas' {ColorForm};

exports
FBColor;

{$R *.res}

begin
end.


unit FrmColor;

interface

uses
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.
AM_WJ 2003-07-10
  • 打赏
  • 举报
回复
转一篇文章给你吧
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;

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

 

在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;
myling 2003-07-10
  • 打赏
  • 举报
回复
要有导出函数呀


否则你调用谁?
universe 2003-07-10
  • 打赏
  • 举报
回复
是用vb中的loadlibrary引用的吗?
lihh 2003-07-10
  • 打赏
  • 举报
回复
在dll中没有定义任何的函数和接口,无法使用,而且在vb中也必须象调用win32 api函数一样使用它们的,请记住!!
myling 2003-07-10
  • 打赏
  • 举报
回复
要有导出函数呀


否则你调用谁?
solonet 2003-07-10
  • 打赏
  • 举报
回复
给分吗?
solonet 2003-07-10
  • 打赏
  • 举报
回复
在DLL中没有定义函数,如何引用呢?

5,386

社区成员

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

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