VS中DLL的导出宏的定义和头文件的位置导致的两类编译错误总结
一般地,我们在新建一个win32的动态链接库(DLL)时,会采取如下的方式的来编写导出接口文件(.h)。
#pragma once#ifndef API_EXPORT
#define DECL_API extern "C" __declspec(dllimport)
#else
#define DECL_API extern "C" __declspec(dllexport)
#endifDECL_API int Add(int a, int b);
如上代码,主要使用了一组预编译宏。这样设计的好处是,可以复用这个头文件。复用的方法是:
1)在客户端,正常包含该头文件即可。不要定义“API_EXPORT”,这个宏。这样客户端编译时将把所有接口看作导入函数。
2)在DLL端,接口函数的实现文件中(.cpp),需要定义宏“API_EXPORT”。这样,DLL编译时将把接口函数当作导出函数。
问题:
在接口函数的实现文件中,需要非常小心宏“API_EXPORT”的定义行与接口头文件包含代码行的位置关系。否则容易导致编译错误,特别是用VS的预编译头文件后。
举例:
用VS2015(其他版本也可以)新建一个名为“Export”的win32 DLL工程(其他默认)。它将生成几个文件,其中关键的文件有:
1)Export.cpp : 在此实现接口函数。
2)stdafx.h :预编译头文件
3)dllmain.cpp : DLL的入口函数。
第一步:
添加一个名为“Export.h”的头文件,代码如上面的代码段。
第二步:
将该头文件包含到“Export.cpp”,并定义“API_EXPORT”宏,然后实现接口函数。如下:
// Export.cpp : 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"#include "Export.h"
#define API_EXPORTDECL_API int Add(int a, int b)
{return a + b;
}
此时,编译报错:“error C2491: “Add”: 不允许 dllimport 函数 的定义”
分析:
很明显,“API_EXPORT”宏的定义应该在包含头文件之前,否则,这个宏没有起作用。
第三步:
调整“API_EXPORT”宏的定义的位置如下:
// Export.cpp : 定义 DLL 应用程序的导出函数。
//
#define API_EXPORT
#include "stdafx.h"#include "Export.h"DECL_API int Add(int a, int b)
{return a + b;
}
编译还是报错,错误信息同上一条。是不是很纳闷???
分析:
再仔细看编译输出,发现在这个Error信息之前,还有一条warning信息和两条note信息,如下:
warning C4603: “API_EXPORT”: 未定义宏或在预编译头使用后定义发生改变
note: 将宏添加到预编译头中,而不是在此处定义
note: 使用预编译头
原来,宏的定义不能放在VS自动生成的这个“stdafx.h”之前,否则也无效。
第四步:
再次调整“API_EXPORT”宏的定义的位置如下:
// Export.cpp : 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"
#define API_EXPORT
#include "Export.h"DECL_API int Add(int a, int b)
{return a + b;
}
编译通过,能够正常导出。
总结:
1)不要忽视warning和note信息。
2)要留意“stdafx.h”。
VS中DLL的导出宏的定义和头文件的位置导致的两类编译错误总结相关推荐
- c++中类的定义与头文件的关系
class Stack: 此句只是作为Stack class的前置申明,只是将calss名次告诉编译器,并未提供此class的任何其他信息.前置申明使得我们可以进行类指针的定义,或以此class作为数 ...
- c++dll导入导出宏定义,出现“无法定义dllimport 实体”和“不允许dllimport 静态数据成员的定义”的问题
问题如下: 建立dll项目后,在Api_Head.hpp头文件中,定义宏: #ifndef API_HEAD_HPP #define API_HEAD_HPP #ifdef API_DLL_COMPI ...
- 将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中
将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中 写这种.h和.cpp文件分开的大程序,虽然对很多人来说很简单,对自己来说算是第一次吧,好好学C++,加油~ 题目:定义Point类,由 ...
- 使用jspdf插件将网页中的内容导出为高保真的pdf文件
文章目录 使用jspdf插件将网页中的内容导出为高保真的pdf文件 1. 将网页中的内容导出为pdf文件的四种方式比较 2. 第一种方式:html2canvas + jspdf 导出网页内容 2.1 ...
- 习题 8.4 在本章第8.3.3节中分别给出了包含类定义的头文件student.h,包含成员函数定义的源文件student.cpp以及包含主函数的源文件main.cpp。请完善该程序,在类中增加。。。
C++程序设计(第三版) 谭浩强 习题8.4 个人设计 习题 8.4 在本章第8.3.3节中分别给出了包含类定义的头文件student.h,包含成员函数定义的源文件student.cpp以及包含主函数 ...
- 习题 8.5 将本章的例8.4改写为一个多文件的程序:1.将类定义放在头文件arraymax.h中;2.将成员函数定义放在源文件arraymax.cpp中;3.主函数放在源文件file1.cpp中。
C++程序设计(第三版) 谭浩强 习题8.5 个人设计 习题 8.5 将本章的例8.4改写为一个多文件的程序: 1.将类定义放在头文件arraymax.h中: 2.将成员函数定义放在源文件arraym ...
- C++声明、定义、类的定义、头文件作用、头文件重复引用
转载至:点击打开链接 C++声明.定义.类的定义.头文件作用.头文件重复引用,不具名空间 转自:http://www.cnblogs.com/rocketfan/archive/2009/10/02/ ...
- C++ : 编译单元、声明和定义、头文件作用、防止头文件在同一个编译单元重复引用、static和不具名空间...
转 自:http://www.cnblogs.com/rocketfan/archive/2009/10/02/1577361.html 1. 编译单元:一个.cc或.cpp文件作为一个编译单元,生成 ...
- CCS中给工程加入C66x CSL库和头文件
CCS中给工程加入C66x CSL库和头文件 下载CSL头文件和库. 下载后解压缩进行安装,我安装的位置为:C:\ti\C6xCSL,装好后"/include/"文件夹下面是CSL ...
最新文章
- 10-20国际电极标准系统
- 5G 标准 — R15
- 一维数组和二位数组作为函数参数进行传递的方式
- Java多线程(二):Callable和FutureTask结合使用获取返回值
- 当退出python时是否释放全部内存_Python面试题:高级特性考察
- 二维数组求最大子矩阵的和
- vba 当前文件名_VBA实践+批量合并pdf
- mysql 分区信息查看
- 电脑安装python后开不了机_ubuntu 安装python3.6后,terminal终端打不开问题
- Linux笔记-rpm与yum的基本概念
- android+场景切换,Android共享元素场景切换动画的实现
- java循环输出_Java实现excel导出(内容循环多个)
- Java 1.7 ThreadPoolExecutor源码解析
- 使用StarUML生成live555类图
- C++11新特性 右值引用与移动语义
- C语言实现行列式计算
- 2.8 转置矩阵及对称矩阵
- 常用公差配合表图_常用的机械测量工具竟然这么多?你知道几个?
- 汤普森算法_什么是汤普森采样(Thompson sampling)?
- ARGB颜色与int相互转换
热门文章
- 基于SpringBoot+Vue的美食分享平台
- 行业分享 | 苏宁聚力:企业内部的一体化数智工作平台
- [附源码]计算机毕业设计JAVA企业人力资源管理系统
- 金升阳 | 更轻更小的R3系列金属导轨电源 ——LI75/120-23BxxR3
- 事件循环-宏任务-微任务
- 国家公务员考试万余岗位发布 国税系统招人最多-国家公务员-公务员考试-岗位
- 对BRD、MRD、PRD、FSD四类产品文档的理解
- 论文笔记:DS-SLAM
- Javaweb-初识(Tomcat服务部署、创建Javaweb项目、Servlet Post请求案例)
- uniapp webview 直接调用原生摄像头拍照 拍视频 img video,通过ajax获取blob(file为特殊的blob)对象并上传到后端服务器