zoukankan      html  css  js  c++  java
  • 【转】DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的两种方式(dllexport与.def文件)

    DLL中导出函数的声明有两种方式:

    一种方式是:在函数声明中加上__declspec(dllexport);
    另外一种方式是:采用模块定义(.def)文件声明,(.def)文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

    方式一:在函数声明中加上__declspec(dllexport)
    /// 在动态链接库程序中
    /// 声明动态链接库(**.dll)的对外接口函数TestFuction
    extern "C" __declspec(dllexport) int TestFuction(int nType,char *strPath,std::vector<string> &vecData)
    {
       ////do anything here////
       return 0;
    }


    /// 在外部希望调用动态链接库的程序中
    /// 加载动态链接库(**.dll)并调用其对外接口TestFuction
    void func()
    {
      //typedef与函数TestFuction类型相同的函数指针为TESTDLL
      typedef int (_cdecl * TESTDLL)(int nType,char *strPath,std::vector<string> &vecData);
      HINSTANCE hmod;
      //加载动态链接库**.dll
      hmod =::LoadLibrary(_TEXT("dll相对路径\**.dll"));
      if(NULL == hmod)
      {
         TRACE("加载**.dll失败");
      }
      //定义一个与函数TestFuction类型相同的函数指针lpproc
      TESTDLL lpproc;
      //搜索**.dll中函数名为TestFuction的对外接口
      lpproc = (TESTDLL)GetProcAddress (hmod,"TestFuction");
      //如果搜索成功
      if(NULL != lpproc)
      {
         int nType = 0;
         char* strPath = "Data";
         std::vector<string> vecData;
         //通过函数指针lpproc调用**.dll的接口函数TestFuction
         int nResult = (*lpproc)(nType,strPath,vecData);
      }
      //...
      //在恰当的时候释放动态链接库**.dll
      FreeLibrary(hmod);
    }


    方式二:采用模块定义(.def)文件声明
    首先创建 一个DLL程序(DllTestDef)
    在*.cpp中
    int __stdcall Add(int numa, int numb)
    {
         return (numa + numb);
    }

    int __stdcall Sub(int numa, int numb)
    {
         return (numa - numb);
    }

    然后创建一个.def的文件,在里面加上

    ;DllTestDef.lib : 导出DLL函数
    ;作者:----
    LIBRARY DllTestDef
    EXPORTS
    Add @ 1
    Sub @ 2

    最后创建一个测试程序:.cpp文件如下:
    #include <iostream>
    #include <windows.h>

    using namespace std;

    typedef int (__stdcall *FUN)(int, int);
    HINSTANCE hInstance;
    FUN   fun;

    int main()
    {
           hInstance = LoadLibrary("DLLTestDef.dll");
           if(!hInstance)
               cout << "Not Find this Dll" << endl;
           fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1));
           if (!fun)
           {
                  cout << "not find this fun" << endl;
           }
           cout << fun(1, 2) << endl;
           FreeLibrary(hInstance);
           return 0;
    }

    说明:
    .def文件的规则为:

    (1)LIBRARY语句说明.def文件相应的DLL;

    (2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

    (3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

    (4)使用__declspec(dllexport)和使用.def文件是有区别的。

    如果你的DLL是提供给VC用户使用的,你只需要把编译DLL时产生的.lib提供给用户,
    它可以很轻松地调用你的DLL。但是如果你的DLL是供VB、PB、Delphi用户使用的,那么会产生一个小麻烦。
    因为VC++编译器对于__declspec(dllexport)声明的函数会进行名称转换,如下面的函数:
    __declspec(dllexport) int __stdcall Add()
    会转换为Add@0,这样你在VB中必须这样声明:
    Declare Function Add Lib "DLLTestDef.dll" Alias "Add@0" () As Long
    @后面的数由于参数类型不同而可能不同。这显然不太方便。所以如果要想避免这种转换,就要使用.def文件方式导出函数了。

  • 相关阅读:
    Largest Rectangle in Histogram
    Valid Sudoku
    Set Matrix Zeroes
    Unique Paths
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Path Sum II
    Path Sum
    Validate Binary Search Tree
    新手程序员 e
  • 原文地址:https://www.cnblogs.com/2018shawn/p/10518124.html
Copyright © 2011-2022 走看看