Delphi调用C++制作的Dll总出错,请指教! ( 积分: 100 )

S

shamohu

Unregistered / Unconfirmed
GUEST, unregistred user!
用Borland C++ 5.5免费编译器,源程序如下,存为testdll.cpp,用命令行:
bcc32 -O2 -WDE “testdll.cpp”
可以生成testdll.dll动态库。

#include <windows.h>
void __declspec(dllexport) dllf(double a, double b){
b = a + 1;
}

在Delphi中:

procedure TForm1.Button1Click(Sender: TObject);
type
TIntFunc=procedure(a: double; b:double);cdecl;
var
Th:Thandle;
MyFunc:TintFunc;
Tp:TFarProc;
temb: double;
begin
Th:=LoadLibrary('D:/Borland/BCC55/Bin/testdll.dll'); {装载DLL}
if Th>0 then
try
Tp:=GetProcAddress(Th,PChar('dllf'));
if Tp<>nil then begin
MyFunc:=TIntFunc(Tp);
MyFunc(2,temb); // {调用dll函数} //这行出错
end
else
ShowMessage('dllf函数没有找到');
finally
FreeLibrary(Th); {释放DLL}
end
else
ShowMessage('testdll.dll没有找到');
end;
end.

运行时总出错,说”dllf函数没有找到“没找到,望高手指点,谢谢。
 
你找一个分析dll的工具看一下,可能c++编译器编译出来的函数名并不是你想像中的
vc++编译器如果自己不指定导出的函数名的话那它的导出函数的名称是加了其它的符号的
在vc++里可以使用
export
xxx,
这种格式来导出函数名的,具体的记不清了,你可以从这方面着手查一查资料
 
C++会给函数重命名.
有两种解决方案可供选择
1.在你的C++函数上加上extern "c".这样编译器就不会把函数重命名了.
2.像楼上说的,用PE工具查看DLL中函数的名字被C++编译器改成什么了.GetProcAddress真正的函数名
 
type
TIntFunc=procedure(a: double; b:double);stdcall;
这样看看可以吗?
 
谢谢大家的帮助。
C++程序现改为:
#include <windows.h>
extern "C" void _declspec(dllexport) dllf(double a, double b){
b = a+1;
}
存为testdll.cpp,用Borland C++5.5命令行编译也成功,输出函数名用Dependency查看有两个:_dllf和___CPPdebugHook,在Delphi中选函数”_dllf“:

procedure TForm1.Button1Click(Sender: TObject);
type
TIntFunc=procedure(a: double; b:double);cdecl;
var
Th:Thandle;
MyFunc:TintFunc;
Tp:TFarProc;
temb: double;
begin
Th:=LoadLibrary('D:/Borland/BCC55/Bin/testdll.dll'); {装载DLL}
if Th>0 then
try
Tp:=GetProcAddress(Th,PChar('dllf'));
if Tp<>nil then begin
MyFunc:=TIntFunc(Tp);
MyFunc(2,temb); // {调用dll函数}
end
else
ShowMessage('dllf函数没有找到');
finally
FreeLibrary(Th); {释放DLL}
end
else
ShowMessage('testdll.dll没有找到');
MyFunc(2,temB);//此句出错
end;
end.

如果不加最后一句:MyFunc(2,temB);,不会出任何错,但加上后,就出错,不知何故?

TIntFunc=procedure(a: double; b:double);cdecl;
改为
TIntFunc=procedure(a: double; b:double);stdcall;
也同样错。请指教。
 
是调用约定的问题.
例如
extern "C" __stdcall void _declspec(dllexport) dllf(double a, double b)
对应Delphi声明称
TIntFunc=procedure(a: double; b:double);stdcall;
对应关系如下
__cdecl cdecl
__fastcall Register
__stdcall stdcall
__pascal pascal
__msfastcall 无
如果都不加调用约定修饰Delphi默认是Register,BCB默认不知道是什么.
反正你就用都加调用约定修饰就行了
 
谢谢wr960204的指导!
但是改了以后还是一样的出错,在C++和Delphi中,试过同时改动cdecl或stdcall都不行,就是最后一句调用函数时出错:
“Access violation at address 01111238, Read of address 01111238"
请赐教!
 
能不能把你的DLL发到我的邮箱里面.我这里没有BC.
wr960204@126.com
 
dll

#include <windows.h>
extern "C" void __declspec(dllexport) __stdcall dllf(double a, double b)
{
b = a + 1;
}

exe


program test;

{$APPTYPE CONSOLE}

uses
System,SysUtils,Windows,Messages;

type
TIntFunc=procedure(a: double; b:double);stdcall;

var
MyFunc:TintFunc;
Tp:TFarProc;

a,b:double;
Th:Thandle;
begin
Th:=LoadLibrary('dll.dll'); {装载DLL}
if Th>0 then
begin
try
Tp:=GetProcAddress(Th,PChar('dllf'));
if Tp<>nil then
begin
MyFunc := TIntFunc(Tp);
MyFunc(3,b);
write('success');
end
else
write('dllf函数没有找到');
finally
FreeLibrary(Th); {释放DLL}
end;

write('dll.dll没有找到');
end;
end.
 
已经发过去了,谢谢帮忙看看!另外Borland C++5.5编译器是免费的,网上可以自由下载使用:http://www.codegear.com/downloads/free/cppbuilder
 
用用你发给我的DLL没问题.
procedure TForm1.Button1Click(Sender: TObject);
var
mh:Thandle;
Func:procedure(a: double; b:double);stdcall;
begin
mh:=LoadLibrary('C:/testdll.dll'); {装载DLL}
if mh <> 0 then
begin
func := GetProcAddress(mh, 'dllf');
if @func = nil then
begin
ShowMessage('找不到函数入口!');
Exit;
end;
Func(1,2);

end
else
ShowMessage('加载失败!');
end;
 
谢谢akirya和wr960204,原来是自己犯了一个错误:在Delphi中调用函数前,把句柄也先给Free了,自然出错。只是还有一问题,在akirya的代码中,调用函数MyFunc(3,b);应该返回的b值为4,但实际返回的却是很小接近0的值?

wr960204的代码中将Func(1,2);改为Func(1,b);,根据C++代码,返回的b值应为2啊。

如何得到正确的b返回值?谢谢啊!
 
你的b是穿值,当然不能返回.
想返回B要C++中
...... dllf(double a, double *b)......
Delphi中
......procedure(a: double; var b:double);.....
 
C++中改为:
extern "C" void __declspec(dllexport) __cdecl dllf(double a, double *b)
{
b = a + 1;
}
确无法编译通过。如改为:
extern "C" void __declspec(dllexport) __cdecl dllf(double a, double *b)
{
*b = a + 1;
}
C++中编译OK,但在Delphi调用时又出错,如何处理?谢谢了。
 
Delphi的b前面你要加var.
晕.你好像Delphi和C++哪个都不懂啊.
 
谢谢wr960204,开始加Var,但也不行,现在加了一试又行了,估计都是自己的错。再次谢谢!
 
extern "C" void __declspec(dllexport) __stdcall dllf(double a, double *b)
对应
TIntFunc=procedure(a: double;var b:double);stdcall;
 
顶部