尝试使用Python来调用CPP的动态链接库§

目录结构§

root:.
├── Cmakelists.txt
├── Makefile
└── src
    ├── mydynamiclib.cpp
    └── test.py

各文件内容§

Cmakelists.txt§
cmake_minimum_required(VERSION 3.0)

# 项目名称
project(myproject)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 20)

# 设置静态链接器标志
set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++")

# 变量定义
set(include_dir "./src")
set(link_dir "./src")
set(library_name "mylibrary")

# 包含目录
include_directories(${include_dir})

# 链接目录
link_directories(${link_dir})

# 查找所有源文件(.cpp 文件)并将它们添加到 SRC 变量
file(GLOB_RECURSE src_files ${include_dir}/*.cpp)

# 查找所有链接库(.a 文件),并将它们添加到 LIBS 变量
file(GLOB_RECURSE lib_files ${link_dir}/*.a)

# 添加动态链接库目标
add_library(${library_name} SHARED ${src_files})

# 设置导出 DLL 时的目标属性
set_target_properties(${library_name} PROPERTIES
    OUTPUT_NAME "mydynamiclib"  # 生成的 DLL 文件名将是 mydynamiclib.dll
)

# 链接外部库
target_link_libraries(${library_name} ${lib_files})
Makefile§
source_dir = .

build_dir = ${source_dir}\build

DCMAKE_RC_COMPILER = C:/msys64/mingw64/bin/x86_64-w64-mingw32-windres

DCMAKE_C_COMPILER = x86_64-w64-mingw32-gcc

DCMAKE_CXX_COMPILER = x86_64-w64-mingw32-g++


all:
    cmake -G "MinGW Makefiles" -DCMAKE_RC_COMPILER=${DCMAKE_RC_COMPILER} -DCMAKE_C_COMPILER=${DCMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${DCMAKE_CXX_COMPILER} -S ${source_dir} -B ${build_dir}
    cd ${build_dir} & make & python ../src/test.py
mydynamiclib.cpp§
#include <iostream>

extern "C" {
void say_hello() { std::cout << "Hello from the DLL!" << std::endl; }
void cout(char *s) { std::cout << s << std::endl; }
int add(int a, int b) { return a + b; }
}
test.py§
import ctypes

lib = ctypes.CDLL("../build/libmydynamiclib.dll")

lib.say_hello.argtypes = None
lib.say_hello.restype = None

lib.say_hello()

lib.add.argtypes = [ctypes.c_int, ctypes.c_int]
lib.add.restype = ctypes.c_int

print(lib.add(1, 2))

lib.cout.argtypes = [ctypes.c_char_p]
lib.cout.restype = None

lib.cout(str(lib.add(1, 2)).encode("ASCII"))
lib.cout(b"hello world!")
lib.cout("你好,世界!".encode("OEM"))

切换到 root 目录下,在终端中输入 make ,得到以下输出。

Hello from the DLL!
3
3
hello world!
你好,世界!

至此,我们通过 Pythonctypes 库调用成功 CPPdll

当我们既需要 Python 的便捷性但还有部分高性能需求时,不妨把高性能模块抽离出来通过 CPP 来代替。

编译 imgui 项目为 dll§

借助 pybind11 将代码导出为 module§