【问题标题】:Cython - importing cython modules and merging them into single shared objectCython - 导入 cython 模块并将它们合并到单个共享对象中
【发布时间】:2017-04-12 14:16:17
【问题描述】:

我正在尝试使用 Cython 将 python 函数包装到 C++ api。我有 2 个模块 sam1.pyx 和 sam2.pyx

## - sam1.pyx
import sam2
cdef public double calc(double x, double y):
  return sam2.calc_sub(x,y)

文件sam2.py的内容如下

## - sam2.py
def calc_sub(x, y):
  return x*y

有了这样的结构,就生成了被包裹的sam1.h以及对应的sam1.so

在Cpp应用中使用过程中,

#include<iostream>
#include<Python.h>
#include"sam1.h"

using namespace std;

int main(){

  Py_Initialize();

  #if PY_MAJOR_VERSION < 3
   initsam1();
  #else
   PyInit_sam1();
  #endif  

  cout << "Starting Program!!"<<endl;

  cout << calc(3, 5);

  Py_Finalize();

  return 0;
}

sam2.py(普通python)未导入,错误为

Exception NameError: "name 'sam2' is not defined" in 'sam1.calc' ignored

您能告诉我缺少什么吗?

【问题讨论】:

  • 我认为因为函数calc_sub是cdef,所以它应该是cimported。 (或者,如果您将calc_sub 设为标准的def 函数,那么您可能可以使用import 它)。我没有尝试过你的代码,所以它可能有点复杂。
  • 我在标准def 和普通import 上遇到同样的错误,我已经上传了文件here
  • 如果我使用cimport,程序会一直执行到另一个模块的函数被引用,然后它会抛出一个错误Segmentation fault (core dumped)。无论是否包含pxd 文件

标签: python cython


【解决方案1】:

问题 1 是您的模块初始化功能失败。在 Python 3 中,您需要针对 NULL 测试输出,然后打印错误(如果发生):

PyObject* m = PyInit_sam1();
if (m==NULL) {
    cout << "Module initialization failed!\n";
    if (PyErr_Occurred()) {
        PyErr_Print();
    }
}

(我不能 100% 确定你为 Python2 做了什么,因为我认为它不会返回任何东西。可能只是 PyErr_Occurred)。这告诉你:

Traceback(最近一次调用最后一次):

文件“sam1.pyx”,第 2 行, init sam1 (sam1.cpp:1094)

导入 sam2

ModuleNotFoundError: 没有名为“sam2”的模块

此回溯希望能为您提供所需的线索 - 它没有找到 sam2。这是因为默认情况下,当前目录不在 C api 程序的路径上。您需要将其设置为 - 以下代码在 Py_Initialize 之后但在模块初始化之前:

PyObject* path = PySys_GetObject("path");
// append "." to the path
PyObject* result = PyObject_CallMethod(path,"append","(s)",".");
Py_XDECREF(result);
// don't decref path though - it's borrowed

它获取sys.path 并将. 附加到它。之后一切正常。


注意 - 如果你从不同的目录调用你的程序,那么 "."指错地方。如果是这种情况,那么您需要做一些更聪明的事情并计算出目录的填充路径,可能来自argv[0]

【讨论】:

  • 错误正是你提到的,path 不正确。它适用于cimportimport 两种情况,即有和没有pxd 文件
  • 但是这些信息不存在于 cython 文档或任何指南中。有这方面的指南吗?
  • 恐怕没有我知道的文档。使用 Python C API 的人通常不会检查是否发生了错误,因此这通常是一个很好的起点。收到该错误消息后,尝试诊断会更容易一些。
  • 还有什么方法可以合并从每个pyx 文件生成的各种shared object 文件?现在要链接应用程序,每次我需要链接所有生成的库。
  • 我相信合并各种共享对象文件是(接近?)不可能的。 Python 导入机制的工作基础是文件都是独立的,并且都有一个适当命名的 init 函数。 Python3 做了 define ways to store multiple modules in one library 但 Cython 没有做任何事情。
猜你喜欢
  • 1970-01-01
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多