从C代码调用Cython函数会引发分段错误 [英] Calling Cython function from C code raises segmentation fault

查看:101
本文介绍了从C代码调用Cython函数会引发分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在C程序中调用cython(cdef)函数。当cdef函数包含python语句时,例如print(0.5)或python(def)函数,调用(cdef)函数会引发分段错误。

I'm trying to call cython (cdef) function in C program. When the cdef function contains python statements, e.g. print(0.5), or python (def) functions, calling the (cdef) function raises a segmentation fault.

.pyx文件:

# cython: language_level=3

cdef public double PI = 3.1415926

cdef public double get_e():
    print("calling get_e()")
    return 2.718281828

.c文件:

#include "Python.h"
#include "transcendentals.h"
#include <math.h>
#include <stdio.h>

int main(int argc, char **argv) {
  Py_Initialize();
  PyInit_transcendentals();
  printf("pi**e: %f\n", pow(PI, get_e()));
  Py_Finalize();
  return 0;
}

编译命令:

cython transcendentals.pyx

gcc -I. -I/usr/include/python3.5m -I/usr/include/python3.5m \
-Wno-unused-result -Wsign-compare \
-g -fstack-protector-strong -Wformat \
-Werror=format-security -DNDEBUG -g \
-fwrapv -O3 -Wall -Wstrict-prototypes \
-L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu \
-L/usr/lib transcendentals.c main.c \
-lpython3.5m -lpthread -ldl -lutil -lm -Xlinker \
-export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

当我删除get_e函数的print语句时,不会出现任何分段错误。但是PI的值为0。

When I remove the print statement of get_e function, no segmentation fault would be raised. But the value of PI will be 0.

推荐答案

我想您正在使用Cython 0.29。 自0.29起 = 3.5的Python版本启用了.python.org / dev / peps / pep-0489 / rel = noreferrer> PEP-489 多阶段模块初始化。这意味着,根据您的经验,使用 PyInit_XXX 不再足够。

I guess you are using Cython 0.29. Since 0.29, PEP-489 multi-phase module initialisation has been enabled for Python versions >=3.5. This means, using PyInit_XXX is no longer sufficient, as you are experiencing.

Cython的文档建议使用 inittab机制,即您的 main 函数应该看起来像这样:

Cython's documentation suggest to use inittab mechanism, i.e. your main-function should look something like:

#include "Python.h"
#include "transcendentals.h"
#include <math.h>
#include <stdio.h>

int main(int argc, char **argv) {
  int status=PyImport_AppendInittab("transcendentals", PyInit_transcendentals);
  if(status==-1){
    return -1;//error
  } 
  Py_Initialize();
  PyObject *module = PyImport_ImportModule("transcendentals");

  if(module==NULL){
     Py_Finalize();
     return -1;//error
  }

  printf("pi**e: %f\n", pow(PI, get_e()));
  Py_Finalize();
  return 0;
}

恢复旧行为的另一种可能性是定义宏 CYTHON_PEP489_MULTI_PHASE_INIT = 0 ,因此例如通过覆盖默认值在命令行上将 -DCYTHON_PEP489_MULTI_PHASE_INIT = 0 传递给gcc。

Another possibility to restore the old behavior would be to define macro CYTHON_PEP489_MULTI_PHASE_INIT=0 and thus overriding the default by e.g. passing -DCYTHON_PEP489_MULTI_PHASE_INIT=0 to gcc on the command line.

这篇关于从C代码调用Cython函数会引发分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆