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
posted @   可乐芬达  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示
主题色彩