在实际的应用中,我们需要动态库导出特定的符号(有些接口不对外暴露,只内部使用),下面的例子展示了具体的实现方式。
code
//log.h
#pragma once
#define BUILDING_DLL
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllexport))
#else
#define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
#endif
#else
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllimport))
#else
#define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
#endif
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif
#include <iostream>
extern "C" DLL_PUBLIC void Log(std::string msg);
DLL_LOCAL void Log_local(std::string msg);
DLL_PUBLIC void Version(void);
//log.cpp
#include "log.h"
void Log(std::string msg) {
std::cout << "Log: " << msg << '\n';
}
void Log_local(std::string msg) {
std::cout << "local Log: " << msg << '\n';
}
void Version(void) {
std::cout << "V 0.0.1" << '\n';
}
上述代码中,Log
和Version
是对外的接口,而同时,Log
利用extern "C"
避免了C++的名字混淆。
msvc
将上述代码在vs2019中生成dll,利用命令查看其导出的符号,
从上图可以看出,Log
和Version
是对外的接口,同时Version
由于名字混淆,变得不太可读。
gcc
将上述代码在linux gcc下生成so,在编译时,可以添加gcc编译选项,
-fvisibility=hidden
因为我用的Cmake,所以也可以,
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
利用命令查看其导出的符号,
从图中可以看出,对外导出的接口为Log
和Version
,同时Version
进行了名字混淆。