请教关于bcb调用vc 的dll的问题!

xxxyyyuuu 2005-04-23 12:32:47
该dll含有对象和类,已有用COFF3OMF.EXE转换后的*.lib,加入工程后编译、链接出现找不到函数的情况,查资料后说需加入一个*.def文件(好像是函数的对照表)
例如:在*.h中申明函数名称doInit();我用bcb中的tdump.exe 导出函数根本找不到'doInit'这个类似函数名,但在转换后的lib中有这个函数名字的串,这个该怎么办啊?
导出后的文本文件中有段EXPORT ord:0534='??0ASK_RBD@@QAE@H@Z'
这个问号'??'是什么意思?是不是有什么不对?

哪位做过类似含有对象和类的dll调用?讲讲您的过程和方法?!!谢谢!!!
...全文
193 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Behard 2005-04-24
  • 打赏
  • 举报
回复
我觉得还是使用 VC 重新包装来实现比较简单
xxxyyyuuu 2005-04-24
  • 打赏
  • 举报
回复
奇怪的是coff格式的lib和我用implib转成omf格式的lib很大不同,不但是大小,而且coff的含有我要调的函数名,而转成omf后就没有了。

急啊,实在不行了,哪位能帮忙看看,我把资料发给您。
谢谢!!!
xxxyyyuuu 2005-04-24
  • 打赏
  • 举报
回复
VC的dll是别的公司开发的,我只有dll文件、lib文件和.h文件,只知道要调用的函数名称是doInit();
cczlp 2005-04-23
  • 打赏
  • 举报
回复
首先确认DLL导出了你要调用的函数, 知道导出函数名或导出序号都可以.
xxxyyyuuu 2005-04-23
  • 打赏
  • 举报
回复
to constantine(飘遥的安吉儿)
你发的资料我看过,我导出来的函数名称里怎么都没有我要的函数名啊?在lib里可以看到这个函数名,所以还是不行啊!
constantine 2005-04-23
  • 打赏
  • 举报
回复
BCB 调用 VC 编写的 DLL
1. 名字分解:
没有名字分解的函数
TestFunction1 // __cdecl calling convention
@TestFunction2 // __fastcall calling convention
TESTFUNCTION3 // __pascal calling convention
TestFunction4 // __stdcall calling convention
有名字分解的函数
@TestFunction1$QV // __cdecl calling convention
@TestFunction2$qv // __fastcall calling convention
TESTFUNCTION3$qqrv // __apscal calling convention
@TestFunction4$qqrv // __stdcall calling convention
使用 extern "C" 不会分解函数名

使用 Impdef MyLib.def MyLib.DLL 生成 def 文件查看是否使用了名字分解

2. 调用约定:
__cdecl 缺省
是 Borland C++ 的缺省的 C 格式命名约定,它在标识符前加一下划线,以保留
它原来所有的全程标识符。参数按最右边参数优先的原则传递给栈,然后清栈。
extaern "C" bool __cdecl TestFunction();
在 def 文件中显示为
TestFunction @1
注释: @1 表示函数的顺序数,将在“使用别名”时使用。

__pascal Pascal格式
这时函数名全部变成大写,第一个参数先压栈,然后清栈。
TESTFUNCTION @1 //def file

__stdcall 标准调用
最后一个参数先压栈,然后清栈。
TestFunction @1 //def file

__fastcall 把参数传递给寄存器
第一个参数先压栈,然后清栈。
@TestFunction @1 //def file

3. 解决调用约定:
Microsoft 与 Borland 的 __stdcall 之间的区别是命名方式。 Borland 采用
__stdcall 的方式去掉了名字起前的下划线。 Microsoft 则是在前加上下划线,在
后加上 @ ,再后跟为栈保留的字节数。字节数取决于参数在栈所占的空间。每一个
参数都舍入为 4 的倍数加起来。这种 Miocrosoft 的 DLL 与系统的 DLL 不一样。

4. 使用别名:
使用别名的目的是使调用文件 .OBJ 与 DLL 的 .DEF 文件相匹配。如果还没有
.DEF 文件,就应该先建一个。然后把 DEF 文件加入 Project。使用别名应不断
修改外部错误,如果没有,还需要将 IMPORTS 部分加入 DEF 文件。
IMPORTS
TESTFUNCTIOM4 = DLLprj.TestFunction4
TESTFUNCTIOM5 = DLLprj.WEP @500
TESTFUNCTIOM6 = DLLprj.GETHOSTBYADDR @51
这里需要说明的是,调用应用程序的 .OBJ 名与 DLL 的 .DEF 文件名是等价的,
而且总是这样。甚至不用考虑调用约定,它会自动匹配。在前面的例子中,函数被
说明为 __pascal,因此产生了大写函数名。这样链接程序不会出错。

5. 动态调用例子
VC DLL 的代码如下:
extern "C" __declspec(dllexport) LPSTR __stdcall BCBLoadVCWin32Stdcall()
{
static char strRetStdcall[256] = "BCB Load VC_Win32 Dll by __stdcall mode is OK!";

return strRetStdcall;
}

extern "C" __declspec(dllexport) LPSTR __cdecl BCBLoadVCWin32Cdecl()
{
static char strRetCdecl[256] = "BCB Load VC_Win32 Dll by __cdecl mode is OK!";

return strRetCdecl;
}

extern "C" __declspec(dllexport) LPSTR __fastcall BCBLoadVCWin32Fastcall()
{
static char strRetFastcall[256] = "BCB Load VC_Win32 Dll by __fastcall mode is OK!";

return strRetFastcall;
}

其实动态调用与调用 BCB 编写的 DLL 没有区别,关键是查看 DLL 的导出函数名字
可以使用 tdump.exe(BCB工具) 或者 dumpbin.exe(VC工具) 查看
tdump -ee MyDll.dll >1.txt (查看 1.txt 文件即可)
由于 VC6 不支持 __pascall 方式,下面给出一个三种方式的例子
void __fastcall TForm1::btnBLVCWin32DynClick(TObject *Sender)
{
/*cmd: tdbump VCWin32.dll >1.txt
Turbo Dump Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International
Display of File VCWIN32.DLL

EXPORT ord:0000='BCBLoadVCWin32Fastcall::'
EXPORT ord:0001='BCBLoadVCWin32Cdecl'
EXPORT ord:0002='_BCBLoadVCWin32Stdcall@0'
*/
if ( !DllInst )
DllInst = LoadLibrary ( "VCWin32.dll" );
if ( DllInst )
{
BCBLoadVCWin32Stdcall = (LPSTR (__stdcall *) () )
GetProcAddress ( DllInst, "_BCBLoadVCWin32Stdcall@0" ); //VC Dll
// GetProcAddress ( DllInst, "BCBLoadVCWin32Stdcall" ); //BCB Dll
if ( BCBLoadVCWin32Stdcall )
{
ShowMessage( BCBLoadVCWin32Stdcall() );
}
else ShowMessage ( "Can't find the __stdcall Function!" );

BCBLoadVCWin32Cdecl = (LPSTR (__cdecl *) () )
GetProcAddress ( DllInst, "BCBLoadVCWin32Cdecl" );
if ( BCBLoadVCWin32Cdecl )
{
ShowMessage( BCBLoadVCWin32Cdecl() );
}
else ShowMessage ( "Can't find the __cdecl Function!" );

//Why?不是 'BCBLoadVCWin32Fastcall::',而是 '@BCBLoadVCWin32Fastcall@0'?
BCBLoadVCWin32Fastcall = (LPSTR (__fastcall *) () )
//GetProcAddress ( DllInst, "BCBLoadVCWin32Fastcall::" );
GetProcAddress ( DllInst, "@BCBLoadVCWin32Fastcall@0" );
if ( BCBLoadVCWin32Fastcall )
{
ShowMessage( BCBLoadVCWin32Fastcall() );
}
else ShowMessage ( "Can't find the __fastcall Function!" );
}
else ShowMessage ( "Can't find the Dll!" );
}

6. 静态调用例子
静态调用有点麻烦,从动态调用中可以知道导出函数的名字,但是直接时(加入 lib 文件到工程文件)

Linker 提示不能找到函数的实现
从 4 看出,可以加入 def 文件连接
(可以通过 impdef MyDll.def MyDll.dll 获得导出表)
建立与 DLL 文件名一样的 def 文件与 lib 文件一起加入到工程文件
上面的 DLL(VCWIN32.dll) 的 def 文件为(VCWIN32.def):
LIBRARY VCWIN32.DLL

IMPORTS
@BCBLoadVCWin32Fastcall = VCWIN32.@BCBLoadVCWin32Fastcall@0
_BCBLoadVCWin32Cdecl = VCWIN32.BCBLoadVCWin32Cdecl
BCBLoadVCWin32Stdcall = VCWIN32._BCBLoadVCWin32Stdcall@0

对应的函数声明和实现如下:
extern "C" __declspec(dllimport) LPSTR __fastcall BCBLoadVCWin32Fastcall();
extern "C" __declspec(dllimport) LPSTR __cdecl BCBLoadVCWin32Cdecl();
extern "C" __declspec(dllimport) LPSTR __stdcall BCBLoadVCWin32Stdcall();

void __fastcall TfrmStatic::btnLoadDllClick(TObject *Sender)
{
ShowMessage ( BCBLoadVCWin32Fastcall() );
ShowMessage ( BCBLoadVCWin32Cdecl() );
ShowMessage ( BCBLoadVCWin32Stdcall() );
}
注意:在 BCB 5.0 中,可能直接按下 F9 是不能通过 Linker 的,请先 Build 一次
注:上面的程序使用 BCB 5.0 与 VC6.0 编译成功
wanxin_sz 2005-04-23
  • 打赏
  • 举报
回复
首先,好好检查一下你的dll中的头文件是否写正确,应该至少要extert "c" 吧!估计最大问题是在你的dll头文件中出了问题!我以前也遇到过的,不过具体是什么原因你要好好检查一下才可以!
chiengod 2005-04-23
  • 打赏
  • 举报
回复
http://search.csdn.net/Expert/topic/523/523102.xml?temp=4.859561E-02
ghyd 2005-04-23
  • 打赏
  • 举报
回复
恰好我前几天刚做完一个软件,就是用cb调用vc的dll
你只要掌握几个关键:
首先,在dll中,因该如下所示输出函数:
extern "C" __declspec(dllexport) (这里是函数的返回值类型) __stdcall youfun_name()
另外,在你的vc工程中的.def文件中,添加如下语句:
exports:
youfun
youfun1
youfun2
.......
这样肯定就没问题了

13,870

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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