Windows的DLL示例

于 2021-05-06 发布

官方有个WalkThrough教程。有些小东西需要注意。

sln

首先是dll的header开头的那几个ifdef。原文是这样的:

1
2
3
4
5
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

第一行的MATHLIBRARY_EXPORTS要特别注意,如果自己的示范库不是叫MathLibrary,比如叫DemoDLL,那么就应该改成DEMODLL_EXPORTS。具体是什么EXPORT,可以看项目属性(Alt+Enter)的C/C++-预处理器预处理器定义里面的值。

否则就会在编译时报错C4273(inconsistent DLL linkage),因为编译器会当成是dll import。

第二个是client app,直接右键引用,把dll那个项目给引进,就可以了。

cmake

相比sln,cmake定义ifdef就自由得多,只要跟CMakeLists.txt里面target_compile_definitions的一致即可。例如CMakeLists.txt是这样:

1
target_compile_definitions(dlldemo PUBLIC MATHLIBRARY_EXPORTS)

那么ifdef就设置成:

1
2
3
4
5
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

另外,需要在顶层CMakeLists.txt里面设置两个OUTPUT_PATH,否则生成的dll不在exe的目录,运行不了:

1
2
3
4
5
6
# 设置dynamic link library的输出位置
# 如果是static link,设置的是ARCHIVE_OUTPUT_DIRECTORY
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 设置exe的输出位置
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

更加理想的情况是将CMAKE_ARCHIVE_OUTPUT_DIRECTORYCMAKE_LIBRARY_OUTPUT_DIRECTORYCMAKE_RUNTIME_OUTPUT_DIRECTORY设置一下1:

1
2
3
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

dllexport添加的位置

对于function:

1
2
3
4
5
// 非template
__declspec(dllexport) void foo();
// template
template<typename T>
__declspec(dllexport) void foo(T var);

注意对于模板函数,export的位置要放在template关键词之后。

对于class(没错,class也要export),要放在class关键字之后、类名之前:

1
class __declspec(dllexport) foo{};

ref

目录