我刚学dll文件的使用,自己写了个程序,dll文件的定义如下:
//dll.h
#ifndef _DLL_H_
#define _DLL_H_#include <windows.h>#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */DLLIMPORT void CALLBACK DllFoo(void);#endif /* _DLL_H_ *///dllmain.cpp
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>
#include <iostream>int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
    return TRUE;
}DLLIMPORT void CALLBACK DllFoo(void)
{
    std::cout<<"这是dll里的函数"; 
}
编译后得到mydll.dll 和 libmydll.a(我用的编译器是devc++,这里的*.a相当于*.lib).
在google里找了以后我用#include "dll.h"并在编译器工程设置里加入链接libmydll.a后使用DllFoo成功,但是用另一种方法,也就是不#include "dll.h",并且不用链接文件,在程序中使用LoadLibrary()却出问题,程序如下:
//main.cpp
#include <windows.h>
#include <iostream>
using namespace std;typedef void (*DllFoo)(void);int main(int argc, char *argv[])
{
    DllFoo _DllFoo;
    HINSTANCE hInstLibrary = LoadLibrary("mydll.dll");
    if (hInstLibrary == NULL)
    {
         cout<<"载入dll失败"<<endl;
         FreeLibrary(hInstLibrary); 
         system("pause");
         return 1;
    }
    _DllFoo = (DllFoo)GetProcAddress(hInstLibrary,"DllFoo");
    if(_DllFoo == NULL)//运行后程序进入这里,显示“转换失败”后结束
    {
         cout<<"转换失败"<<endl;
         FreeLibrary(hInstLibrary);
         system("pause");
         return 1; 
    }
    //以下程序没有运行
    DllFoo();
    cout<<endl;
    FreeLibrary(hInstLibrary);
    system("PAUSE");
    return EXIT_SUCCESS;
}如果把出错那个if(_DllFoo == NULL)的全部语句注释掉程序什么都不会显示。请问是哪里出错了?谢谢!

解决方案 »

  1.   

    "#if BUILDING_DLL
    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    # define DLLIMPORT __declspec (dllimport)
    #endif /* Not BUILDING_DLL */
    "
    dll.h里这些全是编译器自己生成的,我也不懂是啥意思。
      

  2.   

    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    # define DLLIMPORT __declspec (dllimport)2个define 都是DLLIMPORT ,你确定?
      

  3.   

    我的理解
    这两句改
    # define DLLEXPORT __declspec (dllexport)DLLEXPORT void CALLBACK DllFoo(void)
      

  4.   

    谢谢skywoodsky() ,我看了一下编译器的模板文件,可能的确有问题,我照您的改了,也编译通过了,但在main.cpp没改的情况下还是老问题,_DllFoo还是=NULL.
      

  5.   

    你可以看看你的dll 导出函数 是“_DllFoo”吗?可能被修饰过了。
      

  6.   

    是在def文件里看吗?以下是libmydll.def文件的内容:; dlltool --base-file C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/cca00688.base --output-exp mydll.exp --dllname mydll.dll --output-def libmydll.def --no-export-all-symbols --add-stdcall-alias --exclude-symbol=DllMainCRTStartup@12 --def C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp/cca00688.def --output-lib libmydll.a
    EXPORTS
    _Z6DllFoov@0 @ 1
    _Z6DllFoov = _Z6DllFoov@0 @ 2是不是要用DllFoov?
      

  7.   

    把typedef void (*DllFoo)(void)
    改成typedef void (*CALLBACK )(void)试试
      

  8.   


    是改成typedef void (*CALLBACK DllFoo )(void)
      

  9.   

    谢谢,改了之后编译通过但还是“转换失败”
    #include <windows.h>
    #include <iostream>
    using namespace std;typedef void (*CALLBACK DllFoo)(void);int main(int argc, char *argv[])
    {
        DllFoo _DllFoo;
        HINSTANCE hInstLibrary = LoadLibrary("mydll.dll");
        if (hInstLibrary == NULL)
        {
             cout<<"载入dll失败"<<endl;
             FreeLibrary(hInstLibrary); 
             system("pause");
             return 1;
        }
        _DllFoo = (DllFoo)GetProcAddress(hInstLibrary,"DllFoo");
        if(_DllFoo == NULL)
        {
             cout<<"转换失败"<<endl;
             FreeLibrary(hInstLibrary);
             system("pause");
             return 1; 
        }
        _DllFoo();
        cout<<endl;
        FreeLibrary(hInstLibrary);
        system("PAUSE");
        return EXIT_SUCCESS;
    }另外,“Depends"工具是VC里的工具吗?我用的是devc++
      

  10.   

    是的,网上搜搜查看dll的工具。_DllFoo = (DllFoo)GetProcAddress(hInstLibrary,"_Z6DllFoov");这句也不行吗?
      

  11.   

    谢谢cuiqimeng(cuiqimeng) ,用了_DllFoo = (DllFoo)GetProcAddress(hInstLibrary,"_Z6DllFoov");真的就行了!
      

  12.   

    如果要用LoadLibrary载入DLL文件,在定义导出函数的时候最好使用extern "C",阻止编译器给函数改名.
      

  13.   

    谢谢CH3CHO(),我试了一下,如果光在dll.h里这样
    extern "C"
    {
    DLLEXPORT void CALLBACK DllFoo(void);
    }
    def文件里的名字还是会改,但如果同时在dllmain.cpp里
    extern "C"
    {
    int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    {
        return TRUE;
    }DLLEXPORT void CALLBACK DllFoo(void)
    {
        std::cout<<"这是dll里的函数"; 
    }
    }
    名字就没变了,就可以用原来的DllFoo了。
    可惜已经结了贴,没法加分了,谢谢!
      

  14.   

    在cpp的原文件中include dll.h时可以使用
    extern "C"
    {
         #include "dll.h" 
    }
    这样cpp编译器就会按c的方式编译连接进来的文件。
      

  15.   

    sasd asd sd dasd as dasd apublic static void main(String[] args)sdas ads