开发工具:DELPHI5、VC++6
操作系统:WIN98
限制:DLL用VC开发,DELPHI使用
问题:DELPHI可以加载并使用VC写的DLL函数了,但是无法传递参数数值,无论修改DELPHI的传入参数都显示的是一个固定数值,郁闷了……该如何去解决?由于只有一点小问题了,故只把最关键的部分写下来。以下是VC写的DLL函数入口部分
>----------------------------
extern "C" _declspec(dllexport)
void myfunc(int n)
{
char s[255];
MessageBox(NULL,itoa(n,s,10),"传入的值是",0);
}
----------------------------<以下是DELPHI的DLL使用部分
>----------------------------
界面:一个FORM,一个SPINEDIT,一个BUTTONprocedure myfunc(m:integer);far;External 'mydll.dll';//静态加载DLL{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);//一个
begin
myfunc(spinEdit1.Value);//将Form1的一个
end;
----------------------------<
操作系统:WIN98
限制:DLL用VC开发,DELPHI使用
问题:DELPHI可以加载并使用VC写的DLL函数了,但是无法传递参数数值,无论修改DELPHI的传入参数都显示的是一个固定数值,郁闷了……该如何去解决?由于只有一点小问题了,故只把最关键的部分写下来。以下是VC写的DLL函数入口部分
>----------------------------
extern "C" _declspec(dllexport)
void myfunc(int n)
{
char s[255];
MessageBox(NULL,itoa(n,s,10),"传入的值是",0);
}
----------------------------<以下是DELPHI的DLL使用部分
>----------------------------
界面:一个FORM,一个SPINEDIT,一个BUTTONprocedure myfunc(m:integer);far;External 'mydll.dll';//静态加载DLL{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);//一个
begin
myfunc(spinEdit1.Value);//将Form1的一个
end;
----------------------------<
解决方案 »
- 本人想开发日语电子词典 不知词库的数据库文件怎么搞到啊
- MFC新手求助啊!
- 关于CTreeCtrl背景图片问题
- 在VC里怎么判断自己是否掉线了
- 为什么自定义网格控件的给出的示例中可以复制粘贴,可是当在自己的程序中使用这个自定义类的时候却不能复制粘贴了呢?
- 有个机会出国外工作,还是NDIS网络底层开发的,月薪25万日元,在东京,大家说有没有必要去?
- PHOTOSHOP的面板是怎么做出来的?是MODALLESS DIALOG吗?画图的颜料盒是怎么做的?
- 在mdi中,怎么实现saveall功能?
- 我的VS怎么感觉被劫持了
- 为什么Debug版正常,Release版却出现非法操作?
- 高手看题,工具条问题!
- 请教如何使用画椭圆函数ellipse-----请春节大散分!!!!!!!!!!!!
procedure TForm1.Button1Click(Sender: TObject);//一个
begin
myfunc(spinEdit1.Value);//将Form1的一个
end;
----------------------------<应该是:
procedure TForm1.Button1Click(Sender: TObject);//一个BUTTONCLICK事件
begin
myfunc(spinEdit1.Value);//将Form1的一个SPINEDIT数值传入DLL函数
end;
----------------------------<然后弹出对话框里的数就不对了
Function functionname(argment):Boolean;far;External 'DllName'; 其中External关键字后面的引号内是DLL的文件名,该文件一般应放在系统的system目录下,或与调用它的项目同一目录。声明以后即可在Pas文件任何地方引用DLL函数。装载时调用DLL的优点是速度较快,程序间也可共享代码。(2) 运行时调用DLLDLL的另一种调用方法是在运行时调用。这种方法要调用到Windows的API函数LoadLibrary,GetProcAddress,FreeLibrary等。此方法主要用于调用其它语言,特别是C++编译的DLL。假定你欲调用的DLL中包括一个函数:Function checkpwd(pwd:string):boolean;export; 那么,首先在欲调用DLL的程序Type类型声明处加入一句:Type
Tcheckpwd= function(pwd:string):boolean; 此句的作用如同C++中声明的函数指针。然后定义如下变量∶Var
aptr:TFarproc;
lhnd:THandle;
flag:boolean; 其中Aptr,lhnd两变量声明必须有,flag是DLL函数返回值,视情况而定。在调用DLL处加入如下语句进行DLL装载:lhnd:=Loadlibrary('路径:DLL文件名');{如lhnd:=Loadlibrary('c:\project1.dll');
aptr:=GetprocAddress(lhnd,'checkpwd'); 下面可直接调用DLL了:flag:=Tcheckpwd(aptr)( 'pwd');{根据函数填相应的变量参数} 调用完以后,用FreeLibrary释放DLL占用的内存:FreeLibrary(lhnd);
语法:
[Public Private | protected] Function FunctionName([Var] [Arg1:DataType1;]
[Arg2:DataType2;...]) [:ReturnDataType]; far;stdcall;external ‘libname libname’ [Name
AliasName];
调用语句的语法包含下面部分:
关键字Public 可选的。表示函数可以被程序代码中的任意部分访问。
关键字Private 可选的。表示函数在声明类的单元(源代码)外不能访问。
关键字Protected 可选的。部分地表示保护函数,保护元素只能被当前类和它的子类访问。
关键字Function 必需的。表示调用函数,函数有返回值。
FunctionName 必需的。调用外部函数的名称,区分大小写。
关键字Var 可选的。表示通过引用传递参数。函数参数可以用值传递增,也可以通过引用传递。通过引用传传递参数,就意味着它的值没被复制到存放函数例程参数的堆栈中,避免复制就意味着程序执行速度加快了。通过引用传值,这将允许过程和函数改变参数的值。
ArgN:DataTypeN 可选的。参数名以及参数类型,传递的参数类型可以是:Shorint,Smallint,Longint,Integer(16/32),Single,Double,Extended,Currency,Date,Pchar,Object,Variant 等。
ReturnType 可选的。表示函数返回值的类型。
Stdcall 必需的。表示传递约定,这样调用模块(应用程序),与被调用模块(DLL)就使用相同的参数约定。
关键字external 必需的。声明访问外部函数。
Libname 必需的。访问的DLL 名称,16 位Delphi 中外部声明不带扩展名的库名。
Name ‘AliasName’ 可选的。Name 指令可以为外部函数起别名,避免与系统例程和函
数名相冲突。
外部程序调用的DLL 函数,必须遵照下列规则:
a. 必须列在DLL 的exports 子句中。
b. 在Delphi3 中,调用函数还需被声明为stdcall,来使用标准的WIN32 参数传递技
术。代替优化的register 参数传递技术。
c. 在WIN32 中,DLL 可以使用全局数据,该数据将不会通过调用应用程序来分享,每
当应用程序装载DLL 时,它在自己的地址空间中存储着DLL 的全局数据。
Function CommOpen(nPort:integer;nBaud:integer):boolean;Cdecl;
far;External 'Commpro.DLL' name 'CommOpen';
对于静态连接
在定义的时候这样改
procedure myfunc(m:integer);far;External 'mydll.dll';stdcall;
“如果是win98以上的操作系统far就可以不用加了”你可以先试一下,不行的话
再在vc输出的函数定义中再加一个"CALLBACK",如下extern "C" _declspec(dllexport)
void CALLBACK myfunc(int n)
在vc工程里添加一个源文件,把后缀改为def
然后这样写
export
你的函数名
用VC写DLL,DELPHI调用,调试通过VC
//a1.cpp
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
int CALLBACK test(int a)//输出的函数
{
return a+1;
}//a1.def
EXPORTS
testDELPHI下面是动态调用
县声明一个类型
type
TA1 = function (i: integer):integer;stdcall;procedure TForm1.Button1Click(Sender: TObject);
var
h: cardinal;
i: integer;
a1: TA1;
begin
//i:=6;
try
h:=loadlibrary('a1.dll');
@a1:=getprocaddress(h,'test');
i:=a1(9);
showmessage(inttostr(i));
finally
freelibrary(h);
end;
end;
procedure myfunc(m:integer);edecl;External 'mydll.dll';
extern "C" _declspec(dllexport)
WINAPI void myfunc(int n)
{
char s[255];
MessageBox(NULL,itoa(n,s,10),"传入的值是",0);
}
----------------------------<
就对了
C中缺省的调用方式是cdecl,WINAPI实际上就是FAR PASCAL,也就是stdcall。
Delphi中缺省的调用方式为register,far声明没有意义。
这是各种调用方式的参数传递顺序及清栈方法:
Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No
@a1:=getprocaddress(h,'myfunc');//我在VC中申明为myfunc
需要写成
@a1:=getprocaddress(h,'_myfunc@4');
才能正常使用,为什么啊?VC中申明的myfunc怎么用个CALLBACK编译后在DLL中就变名字了啊?还有一事不明,在DELPHI中用动态加载太麻烦了。由于程序没必要中途释放加载的DLL,因此我想采用静态加载(程序启动时加载)的方式,这样写起来也简单些。可以老是有问题,要么参数没传入,要么程序没响应了。我在DELPHI想采用静态加载的方式如下:
function *****;External 'mydll.dll';
该如何修改程序呢?
关于
@a1:=getprocaddress(h,'myfunc');//我在VC中申明为myfunc
需要写成
@a1:=getprocaddress(h,'_myfunc@4');
的问题,我已经在里面说了,好好看看!!!!!静态连结也是一样的
这样就可以了function *****;External 'mydll.dll';stdcall;