首页 > 其他 > 详细

Cython编程入门

时间:2014-04-02 04:14:10      阅读:582      评论:0      收藏:0      [点我收藏+]

    本文主要以[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

运行结果:
bubuko.com,布布扣

二: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;
  }
  
}

在这里我们定义了一个枚举{梅花,方片,红桃,黑桃},定义了一个printCard函数打印传递的牌的花色,同时使用typedef给枚举定义了一个简单形式,且定义了形如printCard函数的函数指针。下面我们就通过Python来调用printCard函数和函数指针。

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,代码也比较简单易懂,分别用函数调用一次和函数指针调用一次,结果如下:

bubuko.com,布布扣





Cython编程入门,布布扣,bubuko.com

Cython编程入门

原文:http://blog.csdn.net/yueguanghaidao/article/details/22760171

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!