【问题标题】:Add python modules to cython for use in c将 python 模块添加到 cython 以在 c 中使用
【发布时间】:2022-01-17 15:22:17
【问题描述】:

我目前正在尝试使用 .so 文件在 c 中编写插件后端。在 c 中这样做可以按我的预期工作。但是我考虑为我的后端编写 python 插件。这是我偶然发现似乎很有前途的 cython 的时候。 我的后端正在调用 .so 文件中的一个函数,并期望返回一个值。

这个函数目前看起来像这样:

cdef public size_t transform_data(char *plugin_arguments, char **buffer):
  printf("Entered function\n")
  print("test\n")
  printf("Test passed\n")
  return 5

有趣的是,printf 工作得很好。但是打印没有。我怀疑这是因为我缺少的 python 模块存在某种链接错误?稍后我希望能够将任何 python 模块添加到该文件中,例如 influxdb 模块。对 influxdb.InfluxDBClient 的调用现在也不起作用,我猜与打印不起作用的原因相同。

我正在使用

编译文件
cythonize -3b some_plugin.pyx

我还尝试使用如下所示的安装文件进行编译:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("some_plugin.pyx"))

我一打打印电话,两者都会导致段错误。

这是我用来调用 .so 文件的代码:

#include "execute_plugin.h"

#include <Python.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

size_t execute_plugin(char file_name[FILE_NAME_SIZE], char *plugin_arguments,
                      char **output_buffer) {
  if (!Py_IsInitialized()) {
    Py_SetPythonHome(L"/home/flo/.local/lib/python3.8");
    Py_SetPath(L"/usr/lib/python3.8");
    Py_Initialize();
  }

  if (!Py_IsInitialized())
    return 0;

  void *plugin;
  size_t (*func_transform_data)(char *plugin_arguments, char **output_buffer);
  char path[PATH_SIZE];
  if (!get_path_to_file(path, PATH_SIZE)) {
    printf("Could not receive the correct path to the plugin %s\n", file_name);
    return 0;
  }
  plugin = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
  if (!plugin) {
    fprintf(stderr, "Error: %s\n", dlerror());
    fprintf(stderr, "Cannot load %s\n", file_name);
    return 0;
  }

  func_transform_data =
      (size_t(*)(char *plugin_arguments, char **output_buffer))dlsym(
          plugin, "transform_data");
  if (!func_transform_data) {
    fprintf(stderr, "Error: %s\n", dlerror());
    dlclose(plugin);
    return 0;
  }

  size_t length = func_transform_data(plugin_arguments, output_buffer);

  printf("Size of answer is %ld\n", length);

  dlclose(plugin);

  Py_Finalize();

  return length;
}

我已尝试使用文档并复制了示例:https://cython.readthedocs.io/en/latest/src/tutorial/embedding.html 在此示例中,我没有使用 .so 文件,而是使用 .c 和 .h 文件,这也是由 cythonize 命令生成的。有趣的是,打印功能正在工作,但是当我尝试添加另一个模块(如 influxdb 模块)并尝试从中调用一个函数时,我也会收到错误。

由于我没有找到很多关于在 c 中使用 cython 代码的信息,我想知道我正在尝试做的事情是否可能,或者是否有更好的方法。

【问题讨论】:

    标签: c segmentation-fault cython .so cythonize


    【解决方案1】:

    很难确定您的问题是什么,因为您实际上并未展示如何调用 Cython 函数。所以接下来是猜测。

    Cython 不生成独立的 C 函数。它生成的函数是 Python 模块的一部分,并且需要初始化该模块。可能发生的情况是 Cython 将查找缓存到全局 print 函数作为模块初始化的一部分。由于您跳过了初始化,因此未设置缓存的 print 函数(因此崩溃)。

    当您阅读文档时,您会看到所有示例("Using Cython declarations from C""Embedding Cython modules...")在使用它之前都会导入该模块。您必须这样做。首选的方法是使用PyImport_AppendInittab()

    第二种可能是您尚未初始化 Python 解释器。同样,这不是可选的。

    【讨论】:

    • 我已编辑问题以添加调用 Cython 函数的代码。事实上,我没有使用 PyImport_AppendInittab()。我会看看添加它。但是在我复制文档 (cython.readthedocs.io/en/latest/src/tutorial/embedding.html) 的情况下, PyImport_AppendInittab() 函数被执行了。这是否意味着我必须为我在 .so 中使用的每个模块执行该函数?
    • 不,只是您在正常 Python 导入机制之外使用的模块。我不知道你如何将它与dlopen 结合起来,但我很害怕。此外,当您完成并重新初始化解释器时,许多 Python 模块(尤其是 Numpy)不起作用,所以希望您只这样做一次
    猜你喜欢
    • 1970-01-01
    • 2021-05-10
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多