本文介绍了Cython:从C程序调用Python代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图制作一个Cython包装器,以便可以从C调用Python代码。由于我希望将包装器与原始代码分开,因此导入时遇到了问题。

I am trying to make a Cython wrapper so I can call Python code from C. I am having issues with import as I would like the wrapper to be separate from original code.

代码以 segfault 结尾。如果将代码编写为python模块并通过 import 导入,则程序会说 name ...未定义。当所有内容都在一个文件中并且不涉及任何导入时,问题就不会显现出来(Cython生成的独立代码在导入时会失败)。从其他Python脚本(编译为.so或live)导入libcimpy.pyx时,代码也能正常工作。

Code below ends in segfault when calling imported function. If the code is written as a python module and imported via import the program says that the name ... is not defined. The problem does not exhibit itself when everything is in one file and there's no import involved (indeed code generated by Cython fails when cimporting). The code works fine as well when libcimpy.pyx is imported from other python script (either compiled to .so or live)

我准备了一个最小的示例。这与实际代码相去甚远,但涵盖了原理。

I have prepared a minimal example. This is far from actual code but covers the principle.

cimpPy.pyx:示例python代码(转换为Cython)

cimpPy.pyx: Sample python code (converted to Cython)

cdef sum(a, b):
    return a + b

cimpPy.pxd

cimpPy.pxd

cdef sum(a, b)

libcimpy.pyx(胶粘剂Cython代码)

libcimpy.pyx (glue Cython code)

cimport cimpPy

cdef public int cSum(int a, int b):
    return cimpPy.sum(a, b)

ci.c(我们要从中调用cimpPy的C代码)

ci.c (c code from which we want to call cimpPy)

#include <stdio.h>
#include <stdlib.h>
#include <Python.h>
#include "libcimp.h"

int main(int argc, char **argv) {
  Py_Initialize();
  initlibcimp();
  int a = 2;
  int b = 3;
  int c = cSum(a, b);
  printf("sum of %d and %d is %d\n", a, b, c);
  Py_Finalize();
  return 0;
}

Makefile

EXECUTABLE = ci

OBJS       = ci.o

CC         = gcc
CFLAGS     = -g -I/usr/include/python2.7 -I$(shell pwd)

LINKER     = g++
LDFLAGS    = -L$(shell pwd) $(shell python-config --ldflags) -lcimp
.PHONY: clean cython

all: cython $(EXECUTABLE)

cython:
    python setup.py build_ext --inplace

.c.o:
    $(CC) $(CFLAGS) -c $<

$(EXECUTABLE) : $(OBJS)
    $(LINKER) -o $(EXECUTABLE) $(OBJS) $(LDFLAGS)

clean:
    rm -rf *.o *.so libcimp.c libcimp.h core build $(EXECUTABLE)

setup.py

from distutils.core import setup, Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext

extensions = [
    Extension("libcimp", ["libcimp.pyx"])
]

setup(
    name = "CIMP",
    cmdclass = {"build_ext": build_ext},
    ext_modules = cythonize(extensions)
)

我打算实现的目标是能够将Python代码插入更大的C系统。假设是用户将能够自己编写Python。 C代码是可以在环境中的代理上运行的模拟引擎。这个想法是可以在python中指定代理和环境的行为,并在必要时传递给引擎进行评估。最好的比喻是使用Python脚本作为映射器的map reduce系统。从这个意义上讲,我想从C而不是从C调用Python。

What I intend to achieve is being able to plug Python code into larger C system. The assumption is that users will be able to write Python themselves. The C code is a simulation engine which can operate on agents in a environment. The idea is that the behaviour of agents and environment can be specified in python and passed to the engine for evaluation when necessary. The best analogy would be a map reduce system where Python scripts are mappers. In this sense I want to call Python from C and not the other way round.

将所有内容转换为Cython,而引人注目的是大型事业。

Converting everything to Cython, while compelling would be to large undertaking.

这是正确的方法吗?为什么import仅在python解释器下有效,而在外部嵌入时却无效?任何建议和参考文章或文档,不胜感激。

Is this the right approach? Why import works only under python interpreter and not when embedded externally? Any suggestions and reference articles or documentation are appreciated.

推荐答案

在此代码中, initlibcimp()实际上失败了,但是您不会立即看到它,因为该错误是通过设置python异常报告的。我不是100%肯定这是正确的方法,但是我可以通过在该调用下面添加以下代码来看到错误:

In this code, the initlibcimp() actually fails, but you don't see it right away because the error is reported by setting a python exception. I'm not 100% sure this is the correct way to do this, but I could see the error by adding the following code below that call:

if (PyErr_Occurred())
{
    PyErr_Print();
    exit(-1);
}

然后,程序将输出:

Traceback (most recent call last):
  File "libcimpy.pyx", line 1, in init libcimpy (libcimpy.c:814)
    cimport cimpPy
ImportError: No module named cimpPy

cimpPy 模块尚未定义,是您需要在调用 initlibcimp之前调用 initcimpPy()

The reason that the cimpPy module is not yet defined, is that you need to do a call to initcimpPy() before calling initlibcimp.

这篇关于Cython:从C程序调用Python代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 17:52
查看更多