本文主要以[Learning Cython Programming]一书中的案列和我自己编写的简单程序来学习Cython。
一:Python调用C函数
mycode.c文件
#include <stdio.h> int myfunc (int x, int y) { printf ("look we are within your c code!!\n"); return x + y; }mycode.h文件:
#ifndef __MYCODE_H__ #define __MYCODE_H__ extern int myfunc (int, int); #endif //__MYCODE_H__我们将通过Python调用myfunc函数。
mycodepy.pyx文件:
cdef extern from "mycode.h": cdef int myfunc (int, int) def callCfunc (): print myfunc (1,2)
cdef是Cython的关键字,说明要引用外部的声明。我们创建一个callCfunc函数是有必要的,这是对C中函数的包装,Cython会处理好Python和C之间的类型转换。
注意当cdef开始一个块的时候,下面所有的类型默认都已添加cdef关键字。我们还可以传递参数给callCFunc,下面是我修改后的mycodepy.pyx文件:
cdef extern from "mycode.h": int myfunc (int, int) def callCfunc (): print myfunc (1,2) def f(a,b): print a,b print myfunc(a,b)
这里还有一点,在定义f时可使用C语言的关键字,如def f(int a,int b),Cython将会优化代码,减少类型转换,增加效率。即使同样的算法,使用C的关键字将带来质的飞跃。
Makefile文件如下:all: cython mycodepy.pyx gcc -g -O2 -fpic -c mycodepy.c -o mycodepy.o `python-config --includes` gcc -g -O2 -fpic -c mycode.c -o mycode.o gcc -g -O2 -shared -o mycodepy.so mycodepy.o mycode.o `python-config --libs` clean: rm -f mycodepy.c *.o *.so
这里需要提示一下,‘python-config‘是编译python时提供的一个命令行工具,目的是更容易的找到Python的头文件和库文件位置。
如在我系统中,
python-config --includes: -I/usr/local/include/python2.6
pyhton-config --libs: -lpthread -ldl -lutil -lm -lpython2.6
运行结果:二:Python中使用C的结构体
mycode.h文件:
#ifndef __MYCODE_H__ #define __MYCODE_H__ struct mystruct { char * string; int integer; char ** string_array; }; extern void printStruct (struct mystruct *); #endif //__MYCODE_H__mycode.c文件:
#include <stdio.h> #include "mycode.h" void printStruct (struct mystruct * s) { printf (".string = %s\n", s->string); printf (".integer = %i\n", s->integer); printf (".string_array = \n"); int i; for (i = 0; i < s->integer; ++i) printf ("\t[%i] = %s\n", i, s->string_array [i]); }我们将通过Python调用printStruct函数:
mycodepy.pyx:
cdef extern from "mycode.h": struct mystruct: char * string int integer char ** string_array void printStruct (mystruct *) def testStruct (): cdef mystruct s cdef char *array [2] s.string = "Hello World" s.integer = 2 array [0] = "foo" array [1] = "bar" s.string_array = array printStruct (&s)我们可以看出结构体也需要块分隔符,这里需要注意当你定义使用C中的类型时,需要明确的使用cdef关键字,告诉编译器你要的是C类型而不是PyObject类型。
注意当使用cdef定义结构体时不需要struct关键字,如上所示。
三:Python中使用C的枚举,typedef和函数指针
mycode.h文件:
#ifndef __MYCODE_H__ #define __MYCODE_H__ typedef enum _cardsuit{ CLUBS, DIAMONDS, HEARTS, SPADES }cardsuit; extern void printCard(cardsuit); typedef void (*pcard)(cardsuit); #endifmycode.c文件:
#include "mycode.h" void printCard(cardsuit c) { switch(c) { case CLUBS: printf("CLUBS\n"); break; case DIAMONDS: printf("DIAMONDS\n"); break; case HEARTS: printf("HEARTS\n"); break; case SPADES: printf("SPADES\n"); break; } }
mycodepy.pyx文件:
cdef extern from "mycode.h": enum _cardsuit: CLUBS,DIAMONDS,HEARTS,SPADES ctypedef _cardsuit cardsuit void printCard(cardsuit) ctypedef void (*pcard)(cardsuit) def Pcard(): cdef cardsuit card_c=CLUBS printCard(card_c) cdef cardsuit card_h=HEARTS cdef pcard p=&printCard p(card_h)Cython中ctypedef等同于C的typedef,代码也比较简单易懂,分别用函数调用一次和函数指针调用一次,结果如下:
原文:http://blog.csdn.net/yueguanghaidao/article/details/22760171