本文主要以[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);
#endif
mycode.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