我在Visual C++ 2003中,建立了一个Win32 DLL项目名叫DllTest2,在“应用程序设置”中选定了“导出符号”,然后在VC自动生成的代码中,有DllTest2.h:// 下列 ifdef 块是创建使从 DLL 导出更简单的
//宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLLTEST2_EXPORTS
// 符号编译的。在使用此 DLL 的
//任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 
// DLLTEST2_API 函数视为是从此 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DLLTEST2_EXPORTS
#define DLLTEST2_API __declspec(dllexport)
#else
#define DLLTEST2_API __declspec(dllimport)
#endif// 此类是从 DllTest2.dll 导出的
class DLLTEST2_API CDllTest2 {
public:
CDllTest2(void);
// TODO: 在此添加您的方法。
};extern DLLTEST2_API int nDllTest2;DLLTEST2_API int fnDllTest2(void);有DllTest2.cpp:
// DllTest2.cpp : 定义 DLL 应用程序的入口点。
//#include "stdafx.h"
#include "DllTest2.h"
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
    return TRUE;
}// 这是导出变量的一个示例
DLLTEST2_API int nDllTest2=0;// 这是导出函数的一个示例。
DLLTEST2_API int fnDllTest2(void)
{
return 42;
}// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 DllTest2.h
CDllTest2::CDllTest2()

return; 
}
就这样编译后得到一些文件,然后建立一个Win32应用程序,想在代码中调用fnDllTest2,该怎样调用呢?
在网上找,找到两个代码片段:
第一个:
HMODULE hModule;
FARPROC lpFunc;
hModule=LoadLibrary("DllTest2.DLL");//调试时hModule为0x10000000
if(hModule)
lpFunc=GetProcAddress(hModule,"fnDllTest2");
if(lpFunc != (FARPROC)NULL))//运行时lpFunc始终为0
a = (*lpFunc)();
FreeLibrary(hModule);第二个:
HMODULE hModule;
typedef int(CALLBACK* fnGetNumber)(void);
fnGetNumber GetNumber;
hModule = LoadLibrary("DllTest2.dll");//调试时hModule为0x10000000
GetNumber =(fnGetNumber)GetProcAddress(hModule,"fnDllTest2");
if(GetNumber)//运行时GetNumber始终为0
a = GetNumber();
FreeLibrary(hModule);
因为lpFunc,GetNumber为0(hModule都不为0,为什么他为0呢),所以无法调用函数fnDllTest2。
这两个代码段有没有错呢,还是它们不适合用来调用VC++2003自动生成的Dll。
怎样在Win32程序中调用DLL中的函数呢,就调用那个上面的fnDllTest2,如果包含DllTest2.h,附加DllTest2.lib就可以调用,不过这样一来,就不用LoadLibrary,GetProcAddress都解决了,可不可以不包含DllTest2.h,不附加DllTest2.lib,调用fnDllTest2呢

解决方案 »

  1.   

    C++ compiler adds extra characters to the function name, so it's not fnDllTest2 anymore.Use the following syntax or .def file to change name.extern "C"
    {
    DLLTEST2_API int fnDllTest2(void)
    {
    return 42;
    }
    }Or you can just add your DLL projects as dependeny project or your EXE, no need to add .lib.Use dumpbin /exports on your DLL to double check exported function name.www.fengyuan.com
      

  2.   

    照楼上所说用上 extern "C" ,在生成DLL时会出现如下错误:
    f:\My Documents\Visual Studio Projects\C++ Projects\7.1\DllTest2\DllTest2.cpp(29): error C2732: 链接规范与“fnDllTest2”的早期规范冲突
    在 DllTest2.h 声明了:#define DLLTEST2_API __declspec(dllexport)extern DLLTEST2_API int nDllTest2;DLLTEST2_API int fnDllTest2(void);的,为什么会就没有了呢。
    包含 DllTest2.h,附加DllTest2.lib后,可以直接调用fnDllTest2,但我不想给其他要用DllTest2.Dll的人提供DllTest2.h啊另外,楼上的话我是半懂不懂哈,因为我的英文很poor!:)
      

  3.   

    Add extern "C" to header file too:// In headerextern "C"
    {
    DLLTEST2_API int fnDllTest2(void);
    }
      

  4.   

    首先,全局函数才能被导出,建议你不要使用这种方法:
    更好的方法是建立一个DEF文件,具体的方法,你可以在MSDN中找到,DEF文件允许你很好地获取到所有的对DLL导出函数的控制,而两位楼上的给出的方法仅能提供有限的控制。
    我担心你一个不小心,不好意思,没有看见所有代码,你的导出函数已经被改名了,
    具体可以通过depends工具来检查,向上面的情况,多半是被改名造成的。
    两位楼上的提出的方法也是为了防止名字篡改
      

  5.   

    包含它的头文件
    连接lib文件
    直接用导出的类声明对象就OK了
      

  6.   

    可能是因为已经有 extern DLLTEST2_API int nDllTest2; 了,所以无法 extern "C" 吧,总是会出现 error C2732: 链接规范与“fnDllTest2”的早期规范冲突 的错误呵呵,没有因为一个不小心使导出函数被改名哈,用depends检查,得到:
    PI: C++
    Ordinal: N/A
    Hint: 2 (0x0002)
    Function:?fnDllTest2@@YAHXZ
    Entry Point: Not Bound
    看其他的DLL,发觉他们的PI是C,这是不是 FengYuanMSFT(袁峰) 说的 extern “C”形成的?呵呵,理解了 FengYuanMSFT(袁峰)的“C++ compiler adds extra characters to the function name, so it's not fnDllTest2 anymore”了哈……
    先去吃饭,待会儿再来,Bye
      

  7.   

    fnDllTest2@@YAHXZ 都被编译器篡改成这副德行了,还嘴硬没被篡改
    或者你根本不知道C++编译器名字篡改这回事?
      

  8.   

    //问题马马虎虎算是解决了。
    //最后的代码是://DllTest2.h
    #ifdef DLLTEST2_EXPORTS
    #define DLLTEST2_API extern "C" __declspec(dllexport)
    #else
    #define DLLTEST2_API extern "C" __declspec(dllimport)
    #endifDLLTEST2_API int fnDllTest2(void);//
    // GetFontName.cpp : 定义 DLL 应用程序的入口点。
    //#include "stdafx.h"
    #include "DllTest2.h"
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
        return TRUE;
    }// 这是导出函数的一个示例。
    DLLTEST2_API int fnDllTest2(void)
    {
    return 42;
    }
      

  9.   

    添加了 extern "C"
    去掉了一个类 和 一个变量