C++实际的项目开发过程中,经常需要将核心功能打包成动态链接库(Dynamic Link Library)供第三方调用,在dll中我们可以不仅可以导出接口函数还可以导出C++类。

下面以简单的示例代码说明如何在C++导出接口函数和类。

1 C++中导出接口函数和导出C++类

1.1 C++动态链接库中的导出代码

在C++的动态链接库中,__declspec(dllexport)用于导出dll中的成员,而__declspec(dllimport)用于导入外部dll中的成员。

所以如果需要导出接口函数和类,需要在dll的代码中预先定义__declspec(dllexport),并将__declspec(dllexport)放在需要导出的接口函数和类之前。

在linux系统中,__declspec(dllexport)不可用,具有相同功能的是__attribute__((visibility ("default")))

1.2 跨平台导出宏的写法

由于Windows和Linux系统的导出代码的不一致性,我们需要对上述的接口进行跨平台封装,示例代码如下

#define EXPORT

/* 定义动态链接库dll的导出 */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)

#ifdef EXPORT
#define EXPORT_API __declspec(dllexport)
#else 
#define EXPORT_API __declspec(dllimport)
#endif

#elif defined(linux) || defined(__linux)

#include <stdlib.h>

#ifdef EXPORT
#define EXPORT_API __attribute__((visibility ("default")))
#else
#endif

#endif

仔细查看上述代码,我们使用EXPORT_API作为统一的导出宏。

1.3 导出接口函数

我们可以使用1.2节中的导出宏EXPORT_API来导出接口函数,这里以简单的加法函数为例

export_function.h

#ifndef EXPORT_FUNCTION_H_
#define EXPORT_FUNCTION_H_

#define EXPORT

/* 定义动态链接库dll的导出 */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)

#ifdef EXPORT
#define EXPORT_API __declspec(dllexport)
#else 
#define EXPORT_API __declspec(dllimport)
#endif

#elif defined(linux) || defined(__linux)

#include <stdlib.h>

#ifdef EXPORT
#define EXPORT_API __attribute__((visibility ("default")))
#else
#endif

#endif

#ifdef __cplusplus
extern "C" {
#endif 

#ifndef EXPORT_API
#define EXPORT_API
#endif

    EXPORT_API int Add(int a, int b);

#ifdef __cplusplus
}
#endif 


#endif // !EXPORT_FUNCTION_H_

export_function.cpp

#include "export_function.h"

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

1.4 导出C++类

我们可以使用1.2节中的导出宏EXPORT_API来导出C++类,下面看一个简单的示例

export_class.h

#ifndef _EXPORT_CLASS_H_
#define _EXPORT_CLASS_H_

#define EXPORT

/* 定义动态链接库dll的导出 */
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)

#ifdef EXPORT
#define EXPORT_API __declspec(dllexport)
#else 
#define EXPORT_API __declspec(dllimport)
#endif

#elif defined(linux) || defined(__linux)

#include <stdlib.h>

#ifdef EXPORT
#define EXPORT_API __attribute__((visibility ("default")))
#else
#endif

#endif

class EXPORT_API Example
{
public:
    Example();
    Example(int a, int b);

public:
    int GetAddResult();

public:
    int m_A;
    int m_B;
};


#endif // !_EXPORT_CLASS_H_

export_class.cpp

#include "export_class.h"

Example::Example()
    :m_A(0),
    m_B(0)
{
}

Example::Example(int a, int b)
    :m_A(a),
    m_B(b)
{
}

int Example::GetAddResult()
{
    return m_A + m_B;
}