【cmake实战六】如何使用编译的库(动态库dll)——windows系统
【cmake实战六】如何使用编译的库(动态库dll)——windows系统
- 一、文件目录
- 1、main.cpp
- 2、CmakeLists.txt
- 3、haha
- 二、构建、编译、运行
- 1、构建(新建build目录,在build目录下执行)
- 2、编译
- 3、运行
- 三、知识讲解
- 1、LoadLibrary
- 2、FreeLibrary
- 3、GetProcAddress
- 4、__declspec
- 5、extern "C"
一、文件目录
1、main.cpp
#include<iostream>
#include<windows.h>
using namespace std;
void loadDll(string dllname, HMODULE& handle)
{
//handle = (handle_t)::LoadLibrary(dllname.c_str());
handle = (HMODULE)::LoadLibrary(dllname.c_str());
}
bool freeDll(HMODULE& handle)
{
bool re = FreeLibrary(handle);
return re;
}
int main()
{
cout<<"hello world"<<endl;
//handle_t handle = nullptr;
HMODULE handle = nullptr;
loadDll("C:\\Users\\jx\\Desktop\\test06\\lib\\Debug\\haha.dll", handle);
if (nullptr == handle)
{
cout << "fail to load dll" << endl;
}
cout << "sucess to load dll" << endl;
typedef void (*print)();
print hahafunc=(print)GetProcAddress(handle, "haha");
hahafunc();
bool re = freeDll(handle);
if (re)
{
cout << "success to unload dll" << endl;
}
return 0;
}
2、CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)
PROJECT(NEWHELLO)
ADD_EXECUTABLE(hello main.cpp)
ADD_SUBDIRECTORY(haha)
SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")
SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")
3、haha
- haha.h
#ifndef HAHA_H
#define HAHA_H
#include<iostream>
extern "C" __declspec(dllexport) void haha();
#endif
- haha.cpp
#include "haha.h"
using namespace std;
void haha()
{
cout<<"haha"<<endl;
}
- CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)
SET(TARGET "haha")
#ADD_LIBRARY(haha STATIC haha.cpp)
ADD_LIBRARY(haha SHARED haha.cpp)
SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")
SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")
二、构建、编译、运行
1、构建(新建build目录,在build目录下执行)
cmake ..
2、编译
devenv.com NEWHELLO.sln /Build "Debug|x64"
3、运行
.\hello.exe
三、知识讲解
1、LoadLibrary
- 进程调用 LoadLibrary 以显式链接到 DLL。 如果函数执行成功,它会将指定的 DLL 映射到调用进程的地址空间中并返回该 DLL 的句柄。 此句柄可以与其他函数(如 GetProcAddress 和 FreeLibrary)一起在显式链接中使用。
- https://docs.microsoft.com/zh-cn/cpp/build/loadlibrary-and-afxloadlibrary?view=msvc-170
- LoadLibrary微软提供,linux下不可用,同linux下的dlopen
2、FreeLibrary
- 当不再需要 DLL 模块时,显式链接到 DLL 的进程会调用 FreeLibrary 函数。 此函数使模块的引用计数递减。 而且,如果引用计数为零,则从进程的地址空间取消映射。
- FreeLibrary微软提供,linux下不可用,同linux下的dlclose
参考- https://docs.microsoft.com/zh-cn/cpp/build/freelibrary-and-afxfreelibrary?view=msvc-170
3、GetProcAddress
- 显式链接到 DLL 的进程会调用 GetProcAddress,以获取 DLL 中导出函数的地址。 可使用返回的函数指针调用 DLL 函数。 GetProcAddress 采用 DLL 模块句柄(由 LoadLibrary返回)作为参数,并采用要调用的函数的名称或函数的导出序号。
- 微软提供,linux下无法使用,同linux下的dlsym
参考:https://docs.microsoft.com/zh-cn/cpp/build/getprocaddress?view=msvc-170
https://www.cnblogs.com/avexer/p/3258291.html
4、__declspec
- dllexportdllimport存储类属性是特定于 C 和 C++ 语言的扩展。 可以使用它们从 DLL 中导出或向其中导入函数、数据和对象。
- 微软提供的,linux下无法使用,同linux下的__attribute__ ((visibility(“default”)))
参考:https://docs.microsoft.com/zh-cn/cpp/cpp/dllexport-dllimport?view=msvc-170
https://blog.csdn.net/yu704645129/article/details/53171315
5、extern “C”
1.使用LoadLibrary函数来加载dll库
2.C/C++中extern关键字详解