You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pybind11扩展模块缺失pyarrow符号:arrow::py::unwrap_table未定义

用pybind11开发Arrow扩展模块时遇undefined symbol错误(指向arrow::py::unwrap_table)

问题描述

我用pybind11开发与Arrow交互的扩展模块,需要实现一个接收arrow::Table作为参数的函数。模块编译成功,但运行时触发ImportError,提示未定义符号_ZN5arrow2py12unwrap_tableEP7_object(即arrow::py::unwrap_table)。已知该符号存在于pyarrow的共享对象文件中,但无法让扩展模块正确找到它。

我希望模块直接使用用户安装的pyarrow自带共享库,避免版本不兼容问题,但缺乏扩展模块开发经验,不清楚这类问题的常规解决方式:是否需要静态链接库?或者有没有办法在运行时让Python定位到共享库?

最小复现示例

demo.cc

#include <pybind11/pybind11.h>
#include <arrow/api.h>
#include <arrow/python/pyarrow.h>

int num_rows(pybind11::object const & py_obj) {
    auto result = arrow::py::unwrap_table(py_obj.ptr());
    if (!result.ok()) {
        throw std::runtime_error("argument must be an Arrow table");
    }
    std::shared_ptr<arrow::Table> table = result.ValueOrDie();
    return table->num_rows();
}

PYBIND11_MODULE(df_test, m)
{
    arrow::py::import_pyarrow();
    m.def("num_rows", &num_rows);
}

pyproject.toml

[build-system]
requires = [
  "setuptools>=42",
  "pybind11>=2.10",
  "pyarrow",
]
build-backend = "setuptools.build_meta"

[project]
name = "demo"
description = ""
version = "0.0.0"
dependencies = ["pyarrow"]

setup.py

from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension
import pyarrow as pa

setup(
        ext_modules=[
            Pybind11Extension(
                name='demo',
                sources=[
                    'demo.cc',
                ],
                include_dirs=[pa.get_include()],

                # 尝试过添加但无效,构建环境的库路径是临时的
                #libraries=pa.get_libraries(),
                #library_dirs=pa.get_library_dirs(),

                cxx_std=17,
            ),
        ],
)

错误复现步骤

$ python -m venv venv
$ . venv/bin/activate
$ pip install .
...
Successfully installed demo-0.0.0 numpy-1.26.4 pyarrow-16.1.0
$ python -c "import demo"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: /home/kale/hacking/snippets/python/pybind11_arrow/venv/lib/python3.12/site-packages/demo.cpython-312-x86_64-linux-gnu.so: undefined symbol: _ZN5arrow2py12unwrap_tableEP7_object

确认符号位置

$ nm -gD venv/lib/python3.12/site-packages/pyarrow/libarrow_python.so | grep unwrap_table
000000000019ad00 T _ZN5arrow2py12unwrap_tableEP7_object

解决方案

方法1:延迟符号解析(推荐,避免版本冲突)

问题根源是:动态链接器加载扩展模块时会立即解析所有未定义符号,但此时arrow::py::import_pyarrow()还未执行,pyarrow的共享库尚未加载。添加延迟解析选项后,符号会在第一次使用时才解析,此时pyarrow已被导入。

修改setup.py中的Pybind11Extension,添加Linux下的延迟解析链接参数:

Pybind11Extension(
    name='demo',
    sources=['demo.cc'],
    include_dirs=[pa.get_include()],
    cxx_std=17,
    extra_link_args=['-Wl,-z,lazy'],  # 延迟解析未定义符号
)

重新安装测试:

pip install . --force-reinstall
python -c "import demo; import pyarrow as pa; tbl = pa.Table.from_arrays([pa.array([1,2,3])], names=['col']); print(demo.num_rows(tbl))"

方法2:显式链接pyarrow共享库

如果方法1不生效,可以显式链接到pyarrow的共享库,并设置运行时库路径。但需注意构建环境与用户环境的路径一致性,可能需要用auditwheel等工具修复wheel包的运行时路径:

Pybind11Extension(
    name='demo',
    sources=['demo.cc'],
    include_dirs=[pa.get_include()],
    libraries=pa.get_libraries(),
    library_dirs=pa.get_library_dirs(),
    runtime_library_dirs=pa.get_library_dirs(),
    cxx_std=17,
)

内容的提问来源于stack exchange,提问作者Kale Kundert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:24:54