您的位置:首页 > 其它

VS中DLL的导出宏的定义和头文件的位置导致的两类编译错误总结

2016-12-29 14:59 369 查看
    一般地,我们在新建一个win32的动态链接库(DLL)时,会采取如下的方式的来编写导出接口文件(.h)。

#pragma once

#ifndef API_EXPORT
#define DECL_API extern "C" __declspec(dllimport)
#else
#define DECL_API extern "C" __declspec(dllexport)
#endif

DECL_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_EXPORT

DECL_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”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐