使用SWIG包装二维向量时的编译与导入错误求助
问题:SWIG包装C++ CSV解析器时的未定义符号错误
我正在为特定CSV Schema编写C基础解析器,尝试用SWIG将函数包装成Python可调用形式。生成包装器后一直出现“StdVectorTraits not found”警告,虽然能通过g编译,但导入共享对象时触发ImportError,提示未定义符号_Z8myVectorRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE。
SWIG接口文件
%module parser; %include "/usr/share/swig4.0/std/std_vector.i"; %include "/usr/share/swig4.0/std/std_iostream.i"; %include "/usr/share/swig4.0/std/std_sstream.i"; %include "/usr/share/swig4.0/std/std_string.i"; %include "/usr/share/swig4.0/std/std_basic_string.i"; %{ #include <vector> #include <fstream> #include <sstream> #include <iostream> std::vector<std::vector<double>> myVector(std::string&); %} %template(doubleVector) std::vector<double>; %template(doubleVecVector) std::vector<std::vector<double>>; std::vector<std::vector<double>> myVector(std::string& path) { std::ifstream file; std::string read; std::vector<std::vector<double>> data; file.open(path); for (int i = 0; i < 21; i++) { std::getline(file, read); } for (int i = 0; i < 32; i++) { std::vector<double> line; std::getline(file, read); std::stringstream ss(read); for (int j = 0; j < 48; j++) { std::getline(ss, read, ','); line.push_back(std::stof(read)); } data.push_back(line); } file.close(); return data; }
错误信息
--------------------------------------------------------------------------- ImportError Traceback (most recent call last) /home/../test.ipynb Cell 1 in <cell line: 1>() ----> 1 import parser File ~/../parser.py:15, in <module> 13 from . import _parser 14 else: ---> 15 import _parser 17 try: 18 import builtins as __builtin__ ImportError: /home/../_parser.so: undefined symbol: _Z8myVectorRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
解决方案
1. 修复函数声明与定义的关联问题
你在%{...%}块中仅声明了myVector函数,但将实现写在了SWIG接口的类型定义区(%}之后)。SWIG生成的包装代码会尝试调用这个声明的函数,但编译时该函数的实现未被正确链接,导致符号未定义。
修改方法:将函数实现移至%{...%}块内部,同时在外部保留函数声明供SWIG生成包装:
%module parser; %include "/usr/share/swig4.0/std/std_vector.i"; %include "/usr/share/swig4.0/std/std_iostream.i"; %include "/usr/share/swig4.0/std/std_sstream.i"; %include "/usr/share/swig4.0/std/std_string.i"; %include "/usr/share/swig4.0/std/std_basic_string.i"; %{ #include <vector> #include <fstream> #include <sstream> #include <iostream> // 函数实现放在这里,确保编译时被包含 std::vector<std::vector<double>> myVector(std::string& path) { std::ifstream file; std::string read; std::vector<std::vector<double>> data; file.open(path); for (int i = 0; i < 21; i++) { std::getline(file, read); } for (int i = 0; i < 32; i++) { std::vector<double> line; std::getline(file, read); std::stringstream ss(read); for (int j = 0; j < 48; j++) { std::getline(ss, read, ','); line.push_back(std::stof(read)); } data.push_back(line); } file.close(); return data; } %} // 模板声明要在函数声明之前 %template(doubleVector) std::vector<double>; %template(doubleVecVector) std::vector<std::vector<double>>; // 供SWIG生成包装的函数声明 std::vector<std::vector<double>> myVector(std::string& path);
2. 消除StdVectorTraits not found警告
该警告源于SWIG未正确识别vector类型的模板映射。确保%template声明在函数声明之前,且与vector类型完全匹配。上述修改已正确配置模板,可解决此警告。
3. 正确编译命令
使用C++编译器编译,确保链接标准库:
# 生成包装代码 swig -c++ -python parser.i # 编译包装代码为目标文件 g++ -fPIC -c parser_wrap.cxx -I/usr/include/python3.x # 生成共享库 g++ -shared parser_wrap.o -o _parser.so
替换python3.x为你的Python版本对应的头文件路径(如python3.8)。
内容的提问来源于stack exchange,提问作者Carter Canedy
相关产品推荐
相关产品推荐

