我用MFC向导建立一个DLL。.h文件:
class Cm1App : public CWinApp
{
public:
Cm1App();// 重写
public:
virtual BOOL InitInstance();
int getx(int x); DECLARE_MESSAGE_MAP()
};…….cpp文件:
int Cm1App::getx( int x )
{
return x;
}……
def文件:
; m1.def : 声明 DLL 的模块参数。LIBRARY      "m1"EXPORTS
    ; 此处可以是显式导出
getx
然后在调用时:
typedef int (*pGetx)(int x);
void CTestView::OnBnClickedButton1()
{
HINSTANCE h= AfxLoadLibrary(L"m1.dll");
if(h)
{
pGetx getx=(pGetx) GetProcAddress(h, "getx");
int x=getx(9); }
}结果运行时报错:
Run-Time Check Failure #0 - 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.这是什么问题呢?该如何解决?

解决方案 »

  1.   

    你需要导出的不是类里面的函数,而是导出整个类...导出类不需要写def文件-----------------------------------------------将类定义改为:class __declspec(dllexport) CInDLL 就可以导出了。这样产生的工程在编译时是正确的但是在使用时会产生错误,因为你包含的头文件中也是使用__declspec(dllexport),而使用这个DLL的工程中并没有引出这个类,而是需要引入这个类)在使用时需要将类定义改为class __declspec(dllimport) CInDLL就可以了。
     使用定义文件可以有效的避免这个问题,这种方法是利用宏定义在不同的地方产生不同的编译代码:1.
    在头文件中加入如下的代码: #ifdef _CLASSINDLL
    #define CLASSINDLL_CLASS_DECL __declspec(dllexport)
    #else
    #define CLASSINDLL_CLASS_DECL __declspec(dllimport)  
    #endif  
    #endif // ClassInDLL_H  
    class CLASSINDLL_CLASS_DECL CInDLL  {
    ...
    };2.
    在实现这个类的CPP文件的顶部加入#define _CLASSINDLL语句。 
    #define _CLASSINDLL  这样一来在使用这个类时就可以不做任何改动了.
      

  2.   

    如果想调用getx ,那么就不要用导出MFC方式,直接dllexport getx 导出对应的函数就可以了,同时注意函数调用约定,防止出现Run-Time Check Failure #0 错误..
      

  3.   

    你这个getx是类的成员函数,直接导出没有意义(当然,你这个 getx直接返回参数的值,可以工作;但普通类的成员函数需要依赖于类对象才有意义)。 所以你还是需要导出类,而不仅仅是成员函数。
      

  4.   

    可以导出成员函数,但是在使用def文件导出时,在使用时,定义的函数指针需要显示声明为_stdcall