上回书说道,如何在vc中使用dev-c++中的类,这次说一个更简单的问题,如何实现vc调用dev-c++的函数。
1、打开dev-c++,新建工程,选择dll,输入工程名testdll,选择c工程,完成后,模板工程生成了两个文件,dll.h 和 dllmain.c,先进行编译,生成libtestdll.a和testdll.dll。
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
DLLIMPORT void HelloWorld (void);
#endif /* _DLL_H_ */
2、打开vs2010,当然vc6、vs2005、vs2008也应该一样。新建一个对话框工程,在对话框设计图上双击“OK”按钮,生成“OK”响应代码,手工添加代码“HelloWorld();”。在stdafx.h中,添加:#include “dll.h”,然后设置工程属性,主要是设置包含路径和库路径。(Dev-c++缺省把所有东西都放到同一个目录里了)。只是使用F7生成,编译应该没有问题,链接时会出现TestPrjDlg.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) void __cdecl HelloWorld(void)" (__imp_?HelloWorld@@YAXXZ),该符号在函数 "public: void __thiscall CTestPrjDlg::OnBnClickedOk(void)" (?OnBnClickedOk@CTestPrjDlg@@QAEXXZ) 中被引用
1>../TestDll/TestPrj.exe : fatal error LNK1120: 1 个无法解析的外部命令。
下面,我们一步步的来修改vc工程与dev-c++工程,使得vc程序能够调用dev-c++的dll库。
1、修改dll.h,如下所示,(蓝色为添加部分),修改以后重新生成。
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport) __stdcall
#else /* Not BUILDING_DLL */
# define DLLIMPORT extern "C" __declspec (dllimport)
#endif /* Not BUILDING_DLL */
2、生成lib文件,(.a文件与.lib文件格式是不同的,但是在vs2010中,附件库直接采用.a我也成功过)。
第一种办法:采用vs的lib.exe工具生成lib。首先,打开libtestdll.def,在exports前输入:LIBRARY “TestDll”,然后在命令行中进入 testdll目录,执行如下命令:
lib /machine:i386 /def:libtestdll.def
将会生成libtestdll.lib文件。这里的Library主要是指要链接到的库,如果不加这行,默认为libtestdll.dll,最后在运行testprj.exe时会提示找不到libtestdll.dll库。
第二种办法,使用dumpbin.exe工具生成.def文件,这个稍微麻烦一些,也是在命令行下输入:
DUMPBIN testdll.dll /EXPORTS /OUT:libtestdll.def
生成后,里面的行数比较多,手工将输出函数之外的内容全部删除,然后,同上,手工添加:Library等。
最后,在vs2010的工程附加库中指定libtestdll.lib,去除最初使用的libtestdll.a文件。
3、修改testprj工程属性,函数调用方式为:stdcall (缺省为 cdecl)。
4、重新生成testprj工程,运行后点击OK,弹出“Hello World From Dll!”,是不是成功了呢?
5、再给HelloWorld()函数添加两个参数,试试,一样成功,完美了!
说明:转来的那篇文章里,说的是在vc下,如何采用显示调用的方式,也就是通过LoadLibrary()和GetProcessAddress()来实现,我在尝试的过程中,如果函数没有参数,还不会有问题,有参数时,老是会出现堆栈平衡的问题,也就是那个检查esp的问题。