c++oding="utf-8" ?>
必须写接口文件(.i)、确保编译环境与Python版本/架构一致、正确配置SWIG命令参数(如-c++ -python -py3 -I);三者缺一不可,否则将出现模块未定义、导入失败或符号错误。

SWIG生成Python包装前必须做好的三件事
不写接口文件(.i)就跑SWIG,结果一定是SWIG Error: No modules defined。SWIG不是自动扫描C++头文件的工具,它需要你明确告诉它“哪些类、函数、变量要暴露给Python”。
-
必须写一个
.i接口文件,哪怕只有三行:%module example %{ #include "mylib.h" %} #include "mylib.h"注意%{ %}块里是原样插入到生成的C++包装代码中的,所以这里要放真实的#include和前置声明。 C++头文件里避免使用未定义符号,比如
std::string要配%include "std_string.i",std::vector要配%include "std_vector.i",否则SWIG会报Unknown type或静默跳过。编译环境要一致:SWIG生成的是CPython扩展,Python版本(如3.9/3.11)、ABI(
abi3与否)、架构(x86_64/arm64)必须和后续用python setup.py build_ext时的环境完全匹配,否则ImportError: dynamic module does not define module export function这类错误几乎必然出现。
用swig -c++ -python生成包装时的关键参数组合
swig -c++ -python -py3 -I./include mymodule.i 这条命令里每个参数都有实际影响:
-
-c++不可省略,否则SWIG按C模式解析,遇到class或std::直接报错。 -
-py3强制生成Python 3兼容代码,不加的话在Python 3.8+下可能触发PyInt_FromLong等已移除API的调用。 -
-I路径必须包含所有被#include的头文件,尤其是你自己的头文件路径;SWIG不读取编译器-I,也不继承Makefile里的路径。 - 不要加
-o手动指定输出C++文件名,让SWIG用默认名(mymodule_wrap.cxx),否则setup.py里Extension的sources容易配错。
常见错误现象:undefined symbol: PyInit_mymodule——多半是忘了-py3,或者Python解释器版本和构建时链接的库不一致。
setup.py里Extension配置最容易漏掉的两个点
setuptools.Extension对象不能只写源文件,C++ ABI和链接依赖必须显式声明:
-
language='c++'必须设,否则distutils默认当C编译,遇到new/delete就失败; -
extra_compile_args=['-std=c++17']要匹配你C++源码的C++标准,特别是用了std::optional或std::string_view时; - 如果C++代码依赖第三方库(如
libboost_system),光写libraries=['boost_system']不够,还得配library_dirs=['/usr/lib/x86_64-linux-gnu'],否则ld: cannot find -lboost_system; - Windows下还要加
define_macros=[('SWIGWIN', None)],不然PyMODINIT_FUNC宏展开会出问题。
Python里import失败的典型原因和快速定位法
运行import mymodule报ModuleNotFoundError或ImportError,先别重跑SWIG:
- 检查生成的
.so(Linux/macOS)或.pyd(Windows)文件是否真在Python模块搜索路径里,用python -c "import sys; print('\n'.join(sys.path))"确认; - 文件名是否匹配模块名:SWIG生成的二进制文件名必须是
mymodule.cpython-311-x86_64-linux-gnu.so这类格式(Python 3.11 + x86_64),名字不对就加载失败; - 用
ldd mymodule.cpython-*.so(Linux)或otool -L(macOS)看动态链接是否缺库,常见如libstdc++.so.6 => not found,说明打包时没静态链接libstdc++,或目标机器没装对应版本; - 如果C++构造函数抛异常,Python侧可能静默失败,建议在
%inline里加简单测试函数,先验证基础调用通路。
SWIG本身不处理C++异常传播,默认把异常吞掉并返回NULL,Python看到的就是SystemError: NULL result without error in PyObject_Call——这个点非常隐蔽,调试时容易绕远。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











