官方有个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_DIRECTORY
、CMAKE_LIBRARY_OUTPUT_DIRECTORY
、CMAKE_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
- 参考stackoverflow。
- 完整的例子在CMakeDLLDemo。