PyArrow Cython封装:Arrow:Table转pyarrow.Table未定义符号错误求助
问题描述
将pyarrow.Table传入C++的arrow::Table后再传回Python时执行失败,报错信息:
trade.cpython-39-x86_64-linux-gnu.so: undefined symbol: _ZNK5arrow6Status8ToStringB5cxx11Ev
排查后怀疑问题出在pyarrow_wrap_table,但不清楚具体修复方法,相关源码文件如下:
table_func.h
#ifndef TABLE_FUNC_H #define TABLE_FUNC_H #include <vector> #include <exception> #include <arrow/api.h> #include <arrow/result.h> #include <memory> namespace MktData { std::shared_ptr<arrow::Table> aggregateTradeTable(const std::shared_ptr<arrow::Table> &); }; #endif
table_func.cpp
#include "table_func.h" std::shared_ptr<arrow::Table> MktData::aggregateTradeTable(const std::shared_ptr<arrow::Table> &trades) { return trades; }
decl.pxd
# distutils: language = c++ from pyarrow.lib cimport * cdef extern from "table_func.h" namespace "MktData": cdef shared_ptr[CTable] aggregateTradeTable(shared_ptr[CTable] &);
trade.pyx
from libcpp cimport bool, vector, memory from pyarrow.lib cimport * from decl cimport aggregateTradeTable def aggregate_trades(obj): cdef shared_ptr[CTable] trades = pyarrow_unwrap_table(obj) if trades.get() == NULL: raise TypeError("not an table") cdef shared_ptr[CTable] result = aggregateTradeTable(trades) if result.get() == NULL: raise TypeError("result incorrect") return pyarrow_wrap_table(result)
setup.py
from setuptools import setup from Cython.Build import cythonize from setuptools import Extension, setup import pyarrow as pa import numpy as np sourcefiles = ['trade.pyx', 'table_func.cpp'] extensions = [Extension("trade", sourcefiles)] ext_modules = cythonize(extensions, gdb_debug=True) for ext in ext_modules: ext.include_dirs.append(pa.get_include()) ext.include_dirs.append(np.get_include()) ext.libraries.extend(pa.get_libraries()) ext.library_dirs.extend(pa.get_library_dirs()) setup(ext_modules=ext_modules, language="c++")
修复方案
这个错误源于C++编译ABI不匹配(尤其是std::string的cxx11版本)或链接时未正确关联Arrow依赖,按以下步骤修复:
1. 修正setup.py的编译与链接参数
确保编译标准、链接参数与pyarrow完全匹配,添加运行时库路径:
from setuptools import setup, Extension from Cython.Build import cythonize import pyarrow as pa import numpy as np sourcefiles = ['trade.pyx', 'table_func.cpp'] extensions = [ Extension( "trade", sourcefiles, language='c++', extra_compile_args=['-std=c++17'], # 匹配pyarrow默认编译标准 extra_link_args=pa.get_link_args() # 直接复用pyarrow的完整链接参数 ) ] ext_modules = cythonize(extensions, gdb_debug=True) for ext in ext_modules: ext.include_dirs.append(pa.get_include()) ext.include_dirs.append(np.get_include()) ext.libraries.extend(pa.get_libraries()) ext.library_dirs.extend(pa.get_library_dirs()) # 添加rpath确保运行时能找到Arrow动态库 ext.extra_link_args.append(f'-Wl,-rpath,{pa.get_library_dirs()[0]}') setup(ext_modules=ext_modules)
2. 修正Cython声明的函数参数签名
在decl.pxd中匹配C++函数的const引用参数:
# distutils: language = c++ from pyarrow.lib cimport * cdef extern from "table_func.h" namespace "MktData": cdef shared_ptr[CTable] aggregateTradeTable(const shared_ptr[CTable] &);
3. 重新编译扩展
清理旧编译产物后重新构建:
rm -rf build/ trade.cpython-39-x86_64-linux-gnu.so python setup.py build_ext --inplace
内容的提问来源于stack exchange,提问作者Rehon
相关产品推荐
相关产品推荐

