c语言调用python模块,c++扩展python

  c语言调用python模块,c++扩展python

  最近看到一些关于pytorh的东西,不得不承认现在很火,有点好奇。下载完代码,发现计算部分基本都是用C写的,真的让我对这个所谓的Python拼音编写框架或者库有点失落。仔细一看,大意是逻辑控制部分是用Python写的。计算部分是用C语言编写的扩展模块,这个扩展模块的界面是纯C语言编写的。不得不说Python和C真的是从C开发加工出来的,不好用的时候就调用C,然后就搞定了。让我们言归正传。想法是把C和SSE,CUDA连接起来。说白了,C扩展模块有一部分是在CPU上运行的。一部分是C和SSE(向量计算)操作的,另一部分是CUDA在GPU上操作的,所以对这个C扩展很好奇,本文阐述一下。

  本文基于Python Cookbook第三版15.2中编写的简单C语言扩展模块。

  目录结构如下:

  其中,示例文件夹如下:

  Sample.c sample.h是标准的C语言程序和头文件,如下所示:

  /* sample.h */

  extern int gcd(int x,int y);

  extern int in_mandel(double x0,double y0,int n);

  extern int divide(int a,int b,int * remainder);

  /* sample.c */

  #包含数学. h

  /*计算最大公约数*/

  int gcd(int x,int y) {

  int g=y;

  while (x 0) {

  g=x;

  x=y % x

  y=g;

  }

  返回g;

  }

  /*测试(x0,y0)是否在Mandelbrot集合中*/

  int in_mandel(double x0,double y0,int n) {

  double x=0,y=0,xtemp

  while (n 0) {

  xtemp=x * x-y * y x0;

  y=2 * x * y y0

  x=xtemp

  n-=1;

  if (x*x y*y 4)返回0;

  }

  返回1;

  }

  /*将两个数相除*/

  int divide(int a,int b,int *remainder) {

  int quot=a/b;

  *余数=a % b;

  返回quot

  }

  gcc共享fPIC sample.c -o libsample.so

  您可以将这个标准的C文件编译成一个标准的动态库,即libsample.so

  这个操作在本文中没有任何意义,只是为了证明C语言文件是正确的。

  在前一个目录中执行以下命令:

  python 3 setup . py build _ ext-in place

  其中sample . cpython-35m-x86 _ 64-Linux-GNU . so是编译后的动态链接库,是我们的扩展模块。

  上述编译操作中setup.py文件的内容如下:

  # setup.py

  从distutils.core导入设置,扩展

  设置(name=sample ,

  ext_modules=[

  扩展(示例),

  [sample/sample.c , pysample.c],

  include_dirs=[sample],

  )

  ]

  其中name是指编译后Python包的名称,没有实际意义,因为我们只需要这个模块是。所以编译后归档。

  [sample/sample.c , pysample.c]是我们写的C语言代码,其中sample.c是我们写的函数代码,pysample.c负责C语言和Python的语言交互。

  扩展名( sample )是模块的名称,即。所以归档吧。名称不能随意更改,必须与pysample.c的定义相同,否则Python中无法识别模块的内容。

  实际上,对于编写Python的C语言扩展来说,重要或困难的不一定是函数代码。这里是sample.c代码,但是负责两种环境下数值转换的代码,即pysample.c这个代码才是真正的扩展需要解决的。

  在某种程度上,pysample.c更像是一个接口,就像头文件对于标准C文件一样。

  测试编译后扩展是否可用:

  #示例. py

  导入样本

  print(sample.gcd(35,42))

  print(sample.in_mandel(0,0,500))

  print(sample.in_mandel(2.0,1.0,500))

  print(sample.divide(42,8))

  =========================================================================

  下面是核心代码,即接口代码或环境转换代码:

  pysample.c

  #包含“Python.h”

  #include sample.h

  /* int gcd(int,int) */

  静态PyObject *py_gcd(PyObject *self,PyObject *args) {

  int x,y,result

  如果(!PyArg_ParseTuple(args, ii ,x,y)) {

  返回NULL

  }

  结果=gcd(x,y);

  返回Py_BuildValue(i ,result);

  }

  /* int in_mandel(double,double,int) */

  静态py object * py _ in _ Mandel(py object * self,PyObject *args) {

  double x0,y0;

  int n;

  (同Internationalorganizations)国际组织结果;

  如果(!PyArg_ParseTuple(args, ddi ,x0,y0,n)) {

  返回空

  }

  result=in_mandel(x0,y0,n);

  返回Py_BuildValue(i ,result);

  }

  /* int divide(int,int,int *) */

  静态py object * py _ divide(py object * self,PyObject *args) {

  int a,b,商,余数;

  如果(!PyArg_ParseTuple(args, ii ,a,b)) {

  返回空

  }

  商=除(甲、乙、余数);

  返回Py_BuildValue((ii),商,余数);

  }

  /*模块方法表*/

  静态PyMethodDef SampleMethods[]={

  {gcd ,py_gcd,METH_VARARGS,最大公约数 },

  {in_mandel ,py_in_mandel,METH_VARARGS, Mandelbrot test},

  {divide ,py_divide,METH_VARARGS,整数除法 },

  { NULL,NULL,0,NULL}

  };

  /*模块结构*/

  静态结构PyModuleDef samplemodule={

  PyModuleDef_HEAD_INIT,

  样本,/*模块名称*/

  样本模块,/* Doc字符串(可能为空)*/

  -1,/*每个解释器状态的大小或-1 */

  样品方法/*方法表*/

  };

  /*模块初始化功能*/

  功能皮莫迪尼特

  PyInit_sample(void) {

  返回PyModule _ Create(示例模块);

  }

  接口文件中:

  /*模块初始化功能*/

  功能皮莫迪尼特

  PyInit_sample(void) {

  返回PyModule _ Create(示例模块);

  }是接口的初始化代码,也是接口代码中唯一的一个非静电函数,该函数非静态允许在计算机编程语言类中调用,也就是导入样本时候的操作。

  返回类型功能皮莫迪尼特说明返回的是模块的创建对象,也就是导入样本中的模块。

  PyInit_sample该函数名的前部分是固定不变的,PyInit_是固定格式,后面跟着的样品则是模块名称PyModule_Create是具体的模块创建代码,其中的参数则是模块结构的说明变量的地址,也就是本文的样本模块变量。1/*模块结构*/

  静态结构PyModuleDef samplemodule={

  PyModuleDef_HEAD_INIT,

  样本,/*模块名称*/

  样本模块,/* Doc字符串(可能为空)*/

  -1,/*每个解释器状态的大小或-1 */

  样品方法/*方法表*/

  };其中,"样本"是模块名称,"样本模块"是模块的文档, -1 表示该模块不能被多个计算机编程语言解释器同时公用(也就是不能保证并发访问的安全性)。

  重点的是样本方法这个是模块中方法的描述变量,也就是方法表。

  模块的描述变量中比较要人不理解的是这个变量PyModuleDef_HEAD_INIT,这个变量形式上来看应该是一个宏定义的变量,这个变量的存在好像并没有什么意义。

  为了进一步了解宏定义变量PyModuleDef_HEAD_INIT查询了以下资料:

  https://份文件。python。org/3/c-API/module。超文本标记语言

  PyModuleDef

  模块定义结构,包含创建模块对象所需的所有信息。对于每个模块,通常只有一个这种类型的静态初始化变量。

  PyModuleDef_Base m_base始终将此成员初始化为PyModuleDef_HEAD_INIT .

  由此可以看出这个变量在计算机编程语言的C扩展中是固定不变的,并没有必要继续深究,固定如此就好。

  不过好奇心使然又接着继续研究了以下,发现下面的资料:

  已经编译好的代码附上:

  环境为Ubuntu 16.04 x86_64

  gcc5.0

  python3.5

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: