开发中用到别人提供的动态库文件 abc.dll,没有头文件,也没有lib,只有一点关于函数声明文档。开始写了一个小测试C程序,动态库加载和函数都没有问题。后来就正式地用到了较的C++中,里面有类和模板。我是在成员函数中加载和使用动态库的。
诡异的问题开始出现了,开始加载调用两个函数,正常。当我又增加了一个成员函数时,这个成员函数没有调用动态库中的函数。编译正常,但是在运行时,程序Crash了,郁闷!我测试了两个方法,
(1)不加载动态库,程序运行正常,说明我增加的成员函数本身没有问题
(2)加载动态库,注释掉成员函数中的代码,程序正常。后来我逐行增加代码,在增到一行很普通的代码时,程序垮掉...
我想到应该是加载库有问题,但是不知道问题出在哪。
之前由于目标机上没有安装VS,所以只能编译成release版本,这也是没有很快找出问题的原因之一。后来忍无可忍安装了VS,编译成Debug版本,噢噢,问题出来了, Debug 信息如下
"The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention"
搜了一下原来是DLL在开发时有个调用方式声明 __stdcall or __cdecl,DLL使用者必须与DLL中声明类型的一致
如 在 abc.h中,fun函数这样声明:
int __cdecl fun(int x, int y);
那么在应用工程中函数指针类型必须定义为:
typedef int(__cdecl* lpfun)(int, int);
检查了一下我的程序,都是用__stdcall声明的指针,改为__cdecl,程序OK!
此外RunLibrary 工程属性与必须与DLL中的属性一致,否则在C++类中 也可能出现问题
DLL工程 Debug Multi-threaded Debug (/MTd) Release: Multi-threaded (/MT)
APP工程 Debug: Multi-threaded Debug DLL (/MDd) Release: Multi-threaded DLL (/MD)
在编写Dll时需要添加 ****.def 到 Linker->Input->"Module Definition File",用于导出symbols