使用 Pyarrow 的 C++ API 的一致示例

A consistent example for using the C++ API of Pyarrow

我正在尝试使用 Pyarrow 的 C++ API。目前官方文档中没有它的例子,这是我能想到的最好的简单的事情:

#include <arrow/python/pyarrow.h>
#include <arrow/python/platform.h>
#include "arrow/python/init.h"
#include "arrow/python/datetime.h"

#include <iostream>

void MyFunction(PyObject * obj)
{
        Py_Initialize();
        std::cout << Py_IsInitialized() << std::endl;
        int ret = arrow_init_numpy();
        std::cout << ret << std::endl;
        if (ret != 0) {
          throw 0;
        }
        ::arrow::py::internal::InitDatetime();

        if(arrow::py::import_pyarrow() != 0)
         {
                std::cout << "problem initializing pyarrow" << std::endl;
                throw 0;}
        std::cout << "test" << std::endl;
        Py_Finalize();
        //return arrow::py::is_array(obj);
}

我正在尝试用

编译它
gcc -pthread -B /home/ziheng/anaconda3/envs/da/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O0 -Wall -Wstrict-prototypes -fPIC -D_GLIBCXX_USE_CXX11_ABI=0 -I/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/numpy/core/include -I/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/pyarrow/include -I/home/ziheng/anaconda3/envs/da/include/python3.7m -c example.cpp -o example.o -std=c++11
g++ -pthread -shared -fPIC -B /home/ziheng/anaconda3/envs/da/compiler_compat -L/home/ziheng/anaconda3/envs/da/lib -Wl,-rpath=/home/ziheng/anaconda3/envs/da/lib -Wl,--no-as-needed -Wl,--sysroot=/ example.o -L/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/pyarrow -l:libarrow.so.600 -l:libarrow_python.so.600 -l:libpython3.7m.so -o example.cpython-37m-x86_64-linux-gnu.so

编译没有问题。但是,当我尝试使用 ctypes 调用编译后的 .so 文件时,如下所示:

from ctypes import *
lib = CDLL('example.cpython-37m-x86_64-linux-gnu.so')
lib._Z10MyFunctionP7_object(1)

我在 arrow_init_numpy 处遇到分段错误,在 Py_IsInitialized() 打印 1 之后。 当我通过 gdb 运行 它时,我 get/tmp/build/80754af9/python_1614362349910/work/Python/ceval.c: 没有那个文件或目录。

但是,如果我尝试将我的 C 代码编译为独立的可执行文件,它可以正常工作。

有人可以帮忙吗?谢谢。

首先,对 Py_Initialize() 的调用是多余的。您正在从 python 中调用您的代码,因此,据推测,python 已经被初始化。如果您正在编写自己的 main 而不是 plugin-type 库,那将是必需的。相应地,调用 Py_Finalize() 可能是个坏主意。

其次,对于手头的错误来说更重要的是,您正在使用 ctypes.CDLL(而不是 ctypes.PyDLL),而 states(强调我的):

The returned function prototype creates functions that use the standard C calling convention. The function will release the GIL during the call. If use_errno is set to true, the ctypes private copy of the system errno variable is exchanged with the real errno value before and after the call; use_last_error does the same for the Windows error code.

最后,Arrow 初始化例程假定您持有 GIL(这可能应该添加到文档中)。因此,修复程序的最简单方法可能是将 CDLL 更改为 PyDLL:

from ctypes import *
lib = PyDLL('example.cpython-37m-x86_64-linux-gnu.so')
lib._Z10MyFunctionP7_object(1)