C++ DLL的生成与调用

一、制作DLL库

1、构建visual studio工程

        可以直接打开vs构建DLL工程,方法如下:

New --> Project --> Dynamic-Link Library(DLL) --> 取名,选路径 --> OK

        另外一种方法就是通过cmake构建(建议大家掌握cmake构建工程,这对于跨平台编译来说非常有用),首先建立好源文件myDll.hpp、myDll.cpp,然后建立CMakeLists.txt文件并编写:

# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(myDLL)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) #将myDll.hpp所在目录包含进来

FILE(GLOB SRC_DLL ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) #将所有cpp文件加入到SRC_DLL变量中

add_library(myDLL SHARED ${SRC_DLL}) #生成dll库

if(MSVC)
    INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/myDll.hpp DESTINATION include_path) #include_path为库头文件输出的目录,由自己指定
    INSTALL(TARGETS myDLL RUNTIME DESTINATION lib_path) #lib_path为dll和lib输出的目录,由自己指定
    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/Release/myDLL.lib DESTINATION lib_path)
endif()

然后建立一个build目录,进入build目录,输入命令:

#win32平台
cmake path_cmake #path_cmake为CMakeLists.txt所在目录

#x64平台
cmake -A x64 path_cmake #path_cmake为CMakeLists.txt所在目录

此时vs工程就在build/myDLL目录下。

2、编写myDll.hpp和myDll.cpp文件

// myDll.hpp file

#pragmaonce

#ifndef DLLEXPT

#defineDLLEXPT __declspec (dllexport)

#endif

int DLLEXPT Add(int a,int b);

// myDll.cpp file
#include"myDll.hpp"

int Add(int a,int b){
    return a+b;
}

        然后就可以在vs上编译生成dll库了,主要生成的有3个文件:myDll.hpp、myDll.dll、myDll.lib文件。注:在myDll.hpp文件中声明接口时一定要在前面加入DLLEXPT,否则不会生成lib文件。

二、调用DLL库

        下面讲一下怎么调用dll库,dll调用方式分为两种:显式调用、隐式调用,为了理解这两种调用方式首先我们来了解一下生成的头文件、lib文件、dll文件。头文件是函数、方法的一些声明,这个文件主要便于调用方在c/c++文件中调用这里面的函数或方法;dll文件是函数和方法的具体实现文件,有点类似于cpp文件;lib文件不止是包含了关于函数和方法的声明,还包含了这些函数、方法的实现文件名(也就是dll文件名)。

 1、隐式调用

        这种方式下,程序启动时就会将dll文件加载到程序中,dll存在于整个程序运行周期中。这种方式的调用只需要分为两步:

        1)包含库的头文件,本例中也就是包含myDll.hpp文件。这一步主要是方便调用方使用myDll.hpp里面声明的函数或方法。

        2)将lib文件编译进应用程序。这一步主要是告诉编译器myDll.hpp(或者myDll.lib)里面声明的函数方法位于哪个实现文件中(这里是myDll.dll),程序启动时就会链接这个实现文件。将lib文件编译进应用程序有两种方法,第一种就是配置一下vs:properties->Configuration Properties->Linker->Input->Additional Dependencies导入lib文件路径即可;第二种就是直接在应用程序源码中#pragma comment(lib,"myDll.lib")。

        一个调用案列如下:

// main.cpp file
#include"myDll.hpp"

#pragma comment(lib,"myDll.lib") #告诉编译器编译时要编译myDll.lib文件

extern "C"_declspec(dllimport) int Add(int a,int b); #也可不要这句,如果写了之后会加速加载dll文件,猜测原因是只加载dll里面的部分函数的实现。

void main(){
    int sum=Add(2,3);
    printf("The sum is %i\n",sum);
}
 

注:在程序运行时需要将dll文件放入动态链接库搜索目录下,比如工程所在的目录或Windows系统目录,否则程序运行时会搜索不到dll文件。

2、显式调用

        顾名思义,显式调用dll文件就是将dll的调用过程显式的写入应用程序中,显示调用也就是苹果系统里面的“懒加载”,应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性。

        显式调用的过程是这样的:在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态链接库调进来,动态链接库的文件名即是上述两个函数的参数,此后再用GetProcAddress()获取想要引入的函数,在应用程序退出之前,用FreeLibrary或MFC提供的AfxFreeLibrary释放动态链接库。调用案例如下:

// main.cpp file
#include <windows.h>  
void main(){  
    typedef int(*pAdd)(int a,int b);  
    HINSTANCE hDLL;  
    pAdd Add
    HDLL=LoadLibrary("myDll.dll");//加载动态链接库myDll.dll文件;  
    Add=(pAdd)GetProcAddress(hDLL,"Add");  
    int sum=Add(2,3);  
    Printf("The sum is %i\n",sum);  
    FreeLibrary(hDLL);//卸载myDll.dll文件;  
} 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值