MST

星途 面试题库

面试题:C++动态库查找加载的跨平台实现

请阐述在Windows和Linux系统下,如何分别实现C++动态库的加载与函数调用,同时考虑到跨平台兼容性,如何设计代码结构使得代码在不同系统上都能正确加载动态库并调用其中函数。
19.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

Windows 系统下 C++ 动态库加载与函数调用

  1. 创建动态库: 在 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;
}
  1. 加载动态库与调用函数
#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++ 动态库加载与函数调用

  1. 创建动态库: 假设创建一个简单的动态库源文件 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;
}

跨平台兼容性代码结构设计

  1. 使用预处理器宏
#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;
}
  1. 使用跨平台库: 可以使用如 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 会根据系统自动选择合适的加载方式,大大简化了跨平台代码编写。