Python 自动读取 CPP 头文件生成 Pybind11 需要的联合编译文件
import re
import sys
def extract_classes(cpp_content):
"""
Extract class names, constructors, and public methods from C++ code.
"""
classes = []
class_pattern = re.compile(
r'class\s+(\w+)\s*{.*?public:\s*(.*?)\s*(?:private:|protected:|};)',
re.DOTALL | re.MULTILINE
)
method_pattern = re.compile(
r'(\w+)\s*\(([^)]*)\)\s*;|'
r'(\w+)\s+(\w+)\s*\(([^)]*)\)\s*(const)?\s*;'
)
for class_match in class_pattern.finditer(cpp_content):
class_name = class_match.group(1)
public_section = class_match.group(2)
ctors, methods = [], []
for match in method_pattern.finditer(public_section):
if match.group(1):
ctors.append(match.group(2).strip())
elif match.group(3):
methods.append({
'name': match.group(4),
'return_type': match.group(3),
'params': match.group(5).strip(),
'const': bool(match.group(6))
})
classes.append({'name': class_name, 'constructors': ctors, 'methods': methods})
return classes
def extract_enums(cpp_content):
"""
Extract enum names and their values from C++ code.
"""
enums = []
enum_pattern = re.compile(
r'typedef\s+enum\s*.*?{([^}]*?)}\s*(\w+)\s*;',
re.DOTALL
)
entry_pattern = re.compile(r'\s*(\w+)\s*(?:=\s*([^,]+))?\s*,?')
for enum_match in enum_pattern.finditer(cpp_content):
enum_name = enum_match.group(2)
entries = []
enum_body = re.sub(r'//.*?$', '', enum_match.group(1), flags=re.MULTILINE)
for entry in entry_pattern.finditer(enum_body.strip()):
entries.append({'name': entry.group(1), 'value': entry.group(2)})
enums.append({'name': enum_name, 'entries': entries})
return enums
def generate_bindings(classes, enums, module_name):
"""
Generate pybind11 binding code for classes and enums.
"""
code = "#include <pybind11/pybind11.h>\nnamespace py = pybind11;\n\n"
for enum in enums:
code += f"void bind_{enum['name']}(py::module &m) {{\n"
code += f" py::enum_<{enum['name']}>(m, \"{enum['name']}\")\n"
for entry in enum['entries']:
code += f" .value(\"{entry['name']}\", {entry['name']})\n"
code += " ;\n}\n\n"
for cls in classes:
code += f"void bind_{cls['name']}(py::module &m) {{\n"
code += f" py::class_<{cls['name']}>(m, \"{cls['name']}\")\n"
for params in cls['constructors']:
param_types = [p.strip().split()[-1] for p in params.split(',')] if params else []
code += f" .def(py::init<{', '.join(param_types)}>())\n" if param_types else " .def(py::init<>())\n"
for method in cls['methods']:
if method['name'] == "ViewModeStateFlowStateMachineModelClass":
continue
const_spec = "const " if method['const'] else ""
code += f" .def(\"{method['name']}\", &{cls['name']}::{method['name']})\n"
code += " ;\n}\n\n"
code += f"PYBIND11_MODULE({module_name}, m) {{\n"
for enum in enums:
code += f" bind_{enum['name']}(m);\n"
for cls in classes:
code += f" bind_{cls['name']}(m);\n"
code += "}\n"
return code
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python generate_pybind11_bindings.py <input.h> [output.cpp]")
sys.exit(1)
input_file, output_file = sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else "bindings.cpp"
module_name = output_file.split('.')[0]
with open(input_file, 'r') as f:
content = f.read()
classes = extract_classes(content)
enums = extract_enums(content)
if not classes and not enums:
print("No classes or enums found.")
sys.exit(0)
with open(output_file, 'w') as f:
f.write(generate_bindings(classes, enums, module_name))
print(f"Bindings generated to {output_file}")
MSVC 编译命令
cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\"
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
set PYTHON_INCLUDE=C:\Users\.conda\envs\dot\include
set PYTHON_LIB=C:\Users\.conda\envs\dot\libs
cl /LD /std:c++14 /EHsc /I %PYTHON_INCLUDE% /I "C:\Users\.conda\envs\dot\lib\site-packages\pybind11\include" View.cpp binding.cpp /link /OUT:View.pyd /DLL %PYTHON_LIB%\python39.lib
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?