面试题答案
一键面试Windows 系统下 C++ 动态库加载与函数调用
- 创建动态库: 在 Visual Studio 中创建一个新的 “动态链接库 (DLL)” 项目。例如,假设定义一个简单的函数在动态库中:
// MyDLL.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API int Add(int a, int b);
// MyDLL.cpp
#include "MyDLL.h"
MYDLL_API int Add(int a, int b) {
return a + b;
}
- 加载动态库与调用函数:
#include <iostream>
#include <windows.h>
typedef int(*AddFunc)(int, int);
int main() {
HINSTANCE hDLL = LoadLibrary(TEXT("MyDLL.dll"));
if (hDLL != NULL) {
AddFunc addFunc = (AddFunc)GetProcAddress(hDLL, "Add");
if (addFunc != NULL) {
int result = addFunc(3, 5);
std::cout << "Result: " << result << std::endl;
}
FreeLibrary(hDLL);
}
return 0;
}
Linux 系统下 C++ 动态库加载与函数调用
- 创建动态库:
假设创建一个简单的动态库源文件
MyLib.cpp
:
// MyLib.h
#ifndef MYLIB_H
#define MYLIB_H
extern "C" int Add(int a, int b);
#endif
// MyLib.cpp
#include "MyLib.h"
int Add(int a, int b) {
return a + b;
}
使用命令编译生成动态库:g++ -shared -o libMyLib.so -fPIC MyLib.cpp
2. 加载动态库与调用函数:
#include <iostream>
#include <dlfcn.h>
typedef int(*AddFunc)(int, int);
int main() {
void* handle = dlopen("./libMyLib.so", RTLD_LAZY);
if (handle != NULL) {
AddFunc addFunc = (AddFunc)dlsym(handle, "Add");
if (addFunc != NULL) {
int result = addFunc(3, 5);
std::cout << "Result: " << result << std::endl;
}
dlclose(handle);
}
return 0;
}
跨平台兼容性代码结构设计
- 使用预处理器宏:
#include <iostream>
#ifdef _WIN32
#include <windows.h>
typedef HINSTANCE DynLibHandle;
#else
#include <dlfcn.h>
typedef void* DynLibHandle;
#endif
// 定义加载动态库函数
DynLibHandle LoadDynamicLibrary(const char* libName) {
#ifdef _WIN32
return LoadLibraryA(libName);
#else
return dlopen(libName, RTLD_LAZY);
#endif
}
// 定义获取函数地址函数
void* GetFunctionAddress(DynLibHandle handle, const char* funcName) {
#ifdef _WIN32
return GetProcAddress((HINSTANCE)handle, funcName);
#else
return dlsym(handle, funcName);
#endif
}
// 定义释放动态库函数
void UnloadDynamicLibrary(DynLibHandle handle) {
#ifdef _WIN32
FreeLibrary((HINSTANCE)handle);
#else
dlclose(handle);
#endif
}
typedef int(*AddFunc)(int, int);
int main() {
DynLibHandle handle;
#ifdef _WIN32
handle = LoadDynamicLibrary("MyDLL.dll");
#else
handle = LoadDynamicLibrary("./libMyLib.so");
#endif
if (handle != NULL) {
AddFunc addFunc = (AddFunc)GetFunctionAddress(handle, "Add");
if (addFunc != NULL) {
int result = addFunc(3, 5);
std::cout << "Result: " << result << std::endl;
}
UnloadDynamicLibrary(handle);
}
return 0;
}
- 使用跨平台库:
可以使用如
Boost.DLL
这样的跨平台库,它提供了统一的接口来加载动态库和调用函数,代码示例如下:
#include <iostream>
#include <boost/dll.hpp>
typedef int(*AddFunc)(int, int);
int main() {
try {
auto lib = boost::dll::shared_library("");
AddFunc addFunc = lib.get<AddFunc>("Add");
int result = addFunc(3, 5);
std::cout << "Result: " << result << std::endl;
} catch (const boost::dll::library_not_found& e) {
std::cerr << "Library not found: " << e.what() << std::endl;
} catch (const boost::dll::symbol_not_found& e) {
std::cerr << "Symbol not found: " << e.what() << std::endl;
}
return 0;
}
在不同系统下,boost::dll::shared_library
会根据系统自动选择合适的加载方式,大大简化了跨平台代码编写。