Cython作为Python到C转换器的示例程序 [英] Example program of Cython as Python to C Converter

查看:44
本文介绍了Cython作为Python到C转换器的示例程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在此处此处可以使用Cython将Python转换为C,但是我找不到任何分步示例。假设我有一个简单的函数:

I found here and here that one can use Cython to convert Python to C, but I cannot find any step-by-step example. Let's say I have a simple function:

foo.pyx

cdef void foo(double* x):
   x[0] = 0.0



来自distutils.core的b

setup.py

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

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

然后我运行: python setup.py build_ext --inplace 以获取foo.c和foo.so文件(以及构建目录)。好吧,我想在main.c中使用翻译的(我希望)foo函数。为了能够使用foo函数,我应该在main.c文件中放入什么内容以及如何对其进行编译?我正在使用gcc。

then I run: python setup.py build_ext --inplace to get foo.c and foo.so files (and build directory). Well, I would like to use translated (I hope) foo function in main.c. What should I put into main.c file and how to compile it in order to be able to use foo function? I am using gcc.

推荐答案

从ac专家那里回来,但是对我来说,使用ubuntu时,以下作品:

Far from a c expert but for me using ubuntu, the following works:

main.c:

#include "foo_api.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     Py_Initialize();
     initfoo();
     import_foo();
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }
     Py_Finalize();
     return 0;
}

foo.pyx:

cdef public api  foo(double* x):
   x[0] = 0.0

从同一目录:

$ cython foo.pyx 

然后:

$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 

然后运行。

$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

我使用 pkg-config --cflags python 来获取标志:

 $ pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 

不调用 Py_Initialize 初始化Python解释器。在应用程序embeddi中ng Python,应在使用任何其他Python / C API函数之前调用它; ),您将获得:

Without calling Py_Initialize (Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions;), you will get:

Fatal Python error: PyThreadState_Get: no current thread
Aborted (core dumped)

没有 initfoo() import_foo()您会得到:

 Segmentation fault (core dumped)

如果不这样做调用 Py_Finalize

Py_Initialize 第二次调用时不进行操作(不首先调用Py_Finalize())。

获取可以运行的文档中的delorean 示例:

main.py:

#include "delorean_api.h"
#include <stdio.h>
Vehicle car;


int main(int argc, char *argv[]) {
     Py_Initialize();
     initdelorean();
     import_delorean();
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     Py_Finalize();
     return 0;
}

delorean.pyx:

delorean.pyx:

ctypedef public struct Vehicle:
    int speed
    float power

cdef api void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        print "Time travel achieved"
    else:
        print("Sorry Marty")

过程相同,唯一的变化是我不得不使用 ctypedef 与Vehicle结构一起使用,或者在主体中使用或使用我没有使用 struct车辆; 在主体中使用:

The procedure is the same, the only change was I had to use ctypedef with the Vehicle struct or else in main or use I had t use struct Vehicle car; in main:

$ cython delorean.pyx
$ cc  -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o delorean  *.c -lpython2.7  
$ ./delorean 1 1
Sorry Marty
$ ./delorean 100 2
Time travel achieved

您也可以使用它,而无需使用 Py_Initialize 等...

You can also get it to work without using Py_Initialize etc...

foo.pyx 中,您只需要使函数public:

In foo.pyx you just need to make the function public:

cdef public  foo(double* x):
   x[0] = 0.0

我添加了 #include< python2.7 / Python.h> 刚刚在main.c中导入了 foo.h 并删除了 Py_Initialize(); 等。仅导入了 python.h 不适用于我,但并非所有人都可以。

I added #include <python2.7/Python.h> just imported foo.hin main.c and removed Py_Initialize(); etc. Just importing python.h would not work for me but that may not be the case for everyone.

#include <python2.7/Python.h>
#include "foo.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }

     return 0;
}

编译相同:

$ cython foo.pyx 
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 
$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

如果您使用的是api版本,则只需按照文档包括api标头,反之亦然,请注意,在给定的C文件中应同时包含modulename.h或modulename_api.h,而不要同时包含二者,否则可能会导致冲突的双重定义。

If you are using the api version then just include the api header or vice versa as per the docs However, note that you should include either modulename.h or modulename_api.h in a given C file, not both, otherwise you may get conflicting dual definitions.

要执行相同的操作在delorean示例中,我不得不使用 libc.stdio 打印字符串以避免分段错误:

To do the same with the delorean example I had to use libc.stdio to print the strings to avoid a segmentation fault:

from libc.stdio cimport printf

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        printf("Time travel achieved\n")
    else:
        printf("Sorry Marty\n")

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;


int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     return 0;
}

返回值可能更有意义:

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public  char* activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        return  "Time travel achieved"
    return "Sorry Marty"

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;

int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     printf("%s\n",activate(&car));
     return 0;
}

这篇关于Cython作为Python到C转换器的示例程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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