dll参数问题~(100分)

  • 主题发起人 主题发起人 wujinhao
  • 开始时间 开始时间
W

wujinhao

Unregistered / Unconfirmed
GUEST, unregistred user!
我用delphi做的dll,vb调用时如何认识vb传过来的字符串参数。我希望dll,delphi/vb都
能够调用!
dll 的函数是这样定义的
function checkserial(ver:integer;name:pchar):boolean;stdcall
vb如何调用?
 
DElphi DLL 说明中加入stdcall关键字VB就可以调用
 
DLL需要注册,用:regsvr32 dll名称
 
如果还是不明白参考一下这个:
C++Builder具有强大的创建Dynamic Link Library 的能力。许多C++Builderr的书藉在创建使用DLL的章节中直接引用的联机文档中的例子。但在Visual C++和VB中直接调用该示例生成的DLL却出现了一些问题,现在我们结合在VB中的调用给出解决方法。示例代码如下所示:

//////////////////////////
// Mydll.cpp ////////////////////////// double dblValue(double); double
halfValue(double); extern __declspec(dllexport) double changeValue(double,
bool); double dblValue(double value) { return value * value; }; double
halfValue(double value) { return value / 2.0; } double changeValue(double
value, bool whichOp) { return whichOp ? dblValue(value) : halfValue(value);
}
---- 对于外部调用函数加入了__declspec(dllexport)修饰成分,这和Visual C++是相同的,说明该函数将自动从DLL中导出,并对任何调用程序可用。然后,对上述代码在C++Builder环境中编译链接生成Mydll.DLL和Mydll.Lib,并将Mydll.DLL拷入Windows/system目录下(由于VB默认的查找DLL的目录为Windows/system)。
---- 在VB5.0中新建一个应用,并添加一个模块,在模块中将函数调用说明如下:

Declare Function changeValue Lib "mydll" (ByVal Value As Double,
ByVal WhichOp As Boolean) As Double
---- 然后在窗体的一个按钮的Click事件中调用changeValue,对该函数进行测试。测试代码如下:
Dim aa As Double
aa = changeValue(10,True)
---- 实际运行中出现了“找不到DLL入口点changeValue in MyDll”的错误信息。
---- 这时利用资源管理中的快速查看功能查看Mydll.DLL,在Export Table中有关信息如下:

Ordinal EntryPoint Name
0000 00013c4 @changeValue$qd4bool

---- 发现changeValue函数除了函数名外之外前后还有@、$等附加字符。查阅有关资料得知这是由于编译器对C++名字的修整造成的,由于Microsoft的Visual C++和Borland的C++ Builder的修整方式不同,在分别修整C++名字的时候,对于相同的函数当然就不会出现相同的名字。好再C++语言通过从系统内定义的函数和对象中删除修整,从而有效地解决这一问题。
---- 将语句extern “C” 放置在程序中的代码块内,编译器就将不会修整这块代码。这时将Mydll.cpp有关代码修改如下:

extern “C” __declspec(dllexport) double changeValue(double, bool);

---- 再次查看重新生成的Mydll.DLL,这时Export table中的有关信息如下:
Ordinal EntryPoint Name 0000 00013c4 _changeValue
---- @、$等字符没有了,但在函数名多了一条”_”线。将Mydll.DLL重新拷入windows/system目录下,并在VB的模块中修改调用说明如下:
Declare Function changeValue Lib "mydll" Alias “_changeValue” (ByVal
Value As Double, ByVal WhichOp As Boolean) As Double
---- 运行VB测试程序,出现”DLL 调用约定错误”的错误提示信息。说明changeValue找到了,只是调用约定不对。我们知道调用约定有__fastcall、__pascal、__stdcall、__cdecl四种方式,而在C++Builder中默认调用约定为__cdecl方式,而VB中调用约定为__stdcall方式。
---- 再将Mydll.cpp的代码修改如下:

extern
“C”__declspec(dllexport) double __stdcall changeValue(double, bool);
…… double __stdcall changeValue(double value, bool whichOp) { return
whichOp ? dblValue(value) : halfValue(value); } ……
---- 这时查看重新编译链接生成的Mydll.DLL,Export table中的有关信息如下:
Ordinal EntryPoint Name
0000 00013c4 changeValue

---- 发现函数名前的“_”线也没有,再次修改VB中调用说明如下:
Declare
Function changeValue Lib "mydll" (ByVal Value As Double, ByVal WhichOp
As Boolean) As Double
---- 运行测试程序,运行结果正确。
---- 后又将__stdcall调用约定方式改__pascal调用约定方式,运行结果同样正确,但改为__fastcall调用约定方式不行。

---- 上面所讨论的解决方法不仅适用VB,该方法同样适样Visual C++,这样使Visual C++和C++ Builder 不同编译器生成的DLL可以互相兼容。

 
delphi 的dll中函数是这样定义的
function checkserial(ver:integer;name:pchar):boolean;stdcall
vb调用是这样定义的
Private Declare Function checkserial Lib "serial.dll" (ByVal ver As Integer, name As String) As Boolean
我的dll可以用vb调用,只是name这个参数vb传过来的是乱吗?在dll中如何认识vb传过来的
字符串参数?
 
wujinhao:
VB中怎么调用,我不知道,但象你在题目中写的那样,是正确的。
在我看来,用Delphi编写DLL时,只要注意两点,就没事了,各种语言都可以调用的。
1.stdcall
2.用PChar,不要用string
 
两点都注意到了,为什么不行呢?
谁有一个使用字符串做参数的简单例子呀?
 
wujinhao:
我总觉得应该是VB调用那边的问题了,但我不懂VB,就帮你提前吧![:)]
 
我见vb调用系统的dll时都是这样调用的
Private Declare Function checkserial Lib "serial.dll" (ByVal ver As Integer, name As String) As Boolean
 
做成象系统那样的DLL格式就可以了吗。参数用PCHAR,不要用string;
 
library demodll;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
Dialogs,
SysUtils,
Classes;

{$R *.res}

function checkserial(ver:integer;name:pchar):boolean;stdcall
begin
Showmessage(name);
end;

Exports
checkserial;

begin
end.
....



Private Declare Function checkserial Lib "C:/demodll.dll" _
(ByVal ver As Long, ByVal name As String) As Boolean
Private Sub CommandButton1_Click()
checkserial 1, "asdfas"
End Sub
 
VB调用时注意几点
1.函数名称的大小写
2.Dll文件的路径是否对
3.变量声明的差异(VB要逐个声明变量)
4.函数不用返回值时不能用"()".(过程更不能用)

以上是我学初VB时的经验。各位高手可能早就知道了。请勿见笑。
 
后退
顶部