首先要知道,头文件是C++的接口文件,不仅本工程需要使用头文件来进行编译,给其他工程提供dll的时候也要提供此dll的头文件才能让其他人通过编程的方式来使用dll。记住:
头文件要给自己用还要给别人用
。
头文件中声明了方法,
在提供者那里方法应该被声明为__declspec(dllexport),在使用者那里,方法应该被声明为__declspec(dllimport)。
比如一个项目中的Class中含有一个静态变量,生成dll的时候只采用了__declspec(dllexport) 如下:
dll工程
#define OS_API_EXPORT __declspec(dllexport)
class OS_API_EXPORT A {static int a;}
A.cpp:
#include “A.h”
static A::a=0; //静态变量的初始化要写在cpp文件中
这样做的时候编译dll工程的时候没有问题,但是如果把dll和头文件提供给别人使用的时候就会出“unsloved symbol a”的问题。
原因是静态成员如果不import,是不能够被编译器从lib文件里找到的。
使用dll的工程在编译时也会将dll相关的头文件列入编译对象,而不会理会dll的cpp文件中的初始化过程,因此会出现a没有定义的情况,这时
__declspec(dllimport)就派上用场了,他会告诉使用dll的工程去lib中找到这个静态变量的定义。提供给别人使用的dll头文件应当写成:
A2.h:
#define OS_API_IMPORT __declspec(dllimport)
class OS_API_IMPORT A {static int a;}
当使用A.dll的工程链接上A2.h后,就不会出现“unsloved symbol a”的问题了。
最终为了方便程序的开发,不用分别写出dll工程的头文件和使用dll工程的头文件,头文件可以写为如下形式:
#define OS_API_IMPORT __declspec(dllimport)
#define OS_API_EXPORT __declspec(dllexport)
#ifdef BUILD_DLL
#define OS_API OS_API_EXPORT //如果是生成dll工程,那么导出
#else
#define OS_API OS_API_IMPORT //如果是生成使用dll的工程,那么导入
#endif
class OS_API A{static int a;}
同时别忘了在dll工程属性下设置预处理器定义BUILD_DLL
首先要知道,头文件是C++的接口文件,不仅本工程需要使用头文件来进行编译,给其他工程提供dll的时候也要提供此dll的头文件才能让其他人通过编程的方式来使用dll。记住:头文件要给自己用还要给别人用。头文件中声明了方法,在提供者那里方法应该被声明为__declspec(dllexport),在使用者那里,方法应该被声明为__declspec(dllimport)。比如一个项目中的Class中含有一个静态变量,生成dll的时候只采用了__declspec(dllexport) 如下:...
__declspec(dllexport)和__declspec(dllimport):
__declspec(dllexport):编译器看到一个变量、函数或者C++类被它修饰,那么它就知道应该在生成的DLL 模块中导出该变量、函数或C++类。
__declspec(dllimport):编译器看到一个变量、函数或者C++类被它修饰,那么它就知道可执行文件或DLL的源文件需要从其它DLL模块中导入一些变量和函数。
DLL的导入段:
构建可执行模块时,可执行模块还可以包含一个导入段,其中列出了所有它需要的DLL模块的名称,对列出的每个DLL
dllexport与dllimport
dllexport与dllimport存储级属性是微软对C和C++的扩展,可用于从dll中导入或导出函数、数据、对象(objects)
__declspec( dllimport ) declarator
__declspec( dllexport ) declarator
这些属性显式地定义了dll提供给客户端的接口,客户端可以是一个可执行文件或者另一个dll。dllexport声明的使用免去了模块定义(.def)文件的使用,def文件至少包含相关导出函数的
一、基本概念
_declspec(dllexport)与_declspec(dllimport)都是DLL内的关键字,即导出与导入。他们是将DLL内部的类与函数以及数据导出与导入时使用的。
主要区别在于:dllexport是在这些类、函数以 及数据的申明的时候使用。用过表明这些东西可以被外部函数使用,即(dllexport)是把DLL中的相关代码(类,函数,数据)暴露出来为其他应用程 序使用。而 dllimport关键字是在外部程序需要使用DLL内相关内容时使用的关键字。
二、初步理解
考虑下面的需求,
一、__declspec(dllexport)
__declspec(dllexport)修饰符是将一个函数声明为导出函数,表示这个函数要被包含它的程序之外的程序调用,一般用于DLL。
__declspec(dllexport) int sum(int a,int b)
//函数体
二、__declspec(dllimport)
声明一个函数的导入,是说明这个函数是从别的DLL导入。
ps:__declspec(dllimport)可以被省略,但是如果使用此关键字,编译器将生成更加高效的代码
个人使用情况:
__declspec( dllimport ) declarator
__declspec( dllexport ) declarator
分别用来从dll导入函数,数据,或对象以及从dll中导出函数,数据,或对象。相当于定义了dll的接口,为它的客户exe或dll定义可使用的函数,数据,或对象。
将函数声明成dllexport就可以免去定义模块定义(.DEF)文件。