windows 下 使用codeblocks 实现C语言对python的扩展

本人比较懒就粘一下别人的配置方案了

从这开始到代码 摘自http://blog.csdn.net/yueguanghaidao/article/details/11538433

一直对Python扩展很感兴趣,刚好看到了Extending and Embedding the Python Interpreter文档,看的是最低版本(由于工作中用的是2.x, ̄□ ̄),官方文档

链接:http://docs.python.org/2.6/extending/index.html

我使用的IDE是Code::Blocks 12.11,首先需要配置一下环境(windows)。

由于需要调用Python提供的C API,需要设置incldue路径,和lib路径。

打开Code::Blocks ->> Settings,

我选择的编译器是GCC,最好看一下安装路径,选择的是CodeBlocks安装时的MinGW, 如果你以前安装过Qt等,可能会有所变化。

下面的编译器和连接器都是MinGW/bin目录下的。

打开Search directories选项卡,找到Python安装路径下的include和libs目录,设置如下:

还需要设置pythonlib文件。

环境配置好了,需要编码了,File ->> New ->> Project,在Projects的类型中我们选择DLL或者是Shared library(共享库)(我选的是DLL),next之后语言选择C,Project title设为testMOD,下面都默认就可以了。

将下面代码覆盖main.c(我从文档中摘取的)------代码摘自  http://blog.csdn.net/kosl90/article/details/6618367

 1 #include <stdio.h>
 2 #include "Python.h"
 3 int sum(int a, int b) {
 4     return a + b;
 5 }
 6
 7 void test() {
 8     printf("2 + 3 is %d\n", sum(2, 3));
 9     printf("23 + 177 is %d\n", sum(23, 177));
10 }
11
12 static PyObject* testMod_sum(PyObject *self, PyObject *args) {
13     int a, b;
14
15     if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
16         return NULL;
17     }
18
19     return (PyObject*)Py_BuildValue("i", sum(a, b));
20 }
21
22 static PyObject* testMod_test(PyObject *self, PyObject *args) {
23     test();
24     return NULL;//原文是  Py_None;
25 }
26
27 static PyMethodDef testModMethods[]= {
28     {"sum", testMod_sum, METH_VARARGS},
29     {"test", testMod_test, METH_VARARGS},
30     {NULL, NULL},
31 };
32
33 PyMODINIT_FUNC inittestMod() {
34     Py_InitModule("testMod", testModMethods);
35 }

然后将上面的代码编译一下,得到

这个testMod.dll就是我们需要的动态库,将它改名为testMod.pyd(python中的pyd其实就是dll),复制到你的python路径/DLLs目录下。

Ok,大功告成,下面就可以使用pyhon调用了。

对于代码的解释 可以参照 代码的原贴 (链接在上面)

下面是对于C语言如何扩展python的一些知识 贴一下:原贴http://www.ibm.com/developerworks/cn/linux/l-pythc/

(如果只是关注扩展的话直接跳到扩展那一节就可以了)

一、简介

Python是一门功能强大的高级脚本语言,它的强大不仅表现在其自身的功能上,而且还表现在其良好的可扩展性上,正因如此,Python已经开始受到越来越多人的青睐,并且被屡屡成功地应用于各类大型软件系统的开发过程中。

与其它普通脚本语言有所不同,Python程序员可以借助Python语言提供的API,使用C或者C++来对Python进行功能性扩展,从而即可以利用Python方便灵活的语法和功能,又可以获得与C或者C++几乎相同的执行性能。执行速度慢是几乎所有脚本语言都具有的共性,也是倍受人们指责的一个重要因素,Python则通过与C语言的有机结合巧妙地解决了这一问题,从而使脚本语言的应用范围得到了很大扩展。

在用Python开发实际软件系统时,很多时候都需要使用C/C++来对Python进行扩展。最常见的情况是目前已经存在一个用C编写的库,需要在Python语言中使用该库的某些功能,此时就可以借助Python提供的扩展功能来实现。此外,由于Python从本质上讲还是一种脚本语言,某些功能用Python实现可能很难满足实际软件系统对执行效率的要求,此时也可以借助Python提供的扩展功能,将这些关键代码段用C或者C++实现,从而提供程序的执行性能。

本文主要介绍Python提供的C语言扩展接口,以及如何使用这些接口和C/C++语言来对Python进行功能性扩展,并辅以具体的实例讲述如何实现Python的功能扩展。

回页首

二、Python的C语言接口

Python是用C语言实现的一种脚本语言,本身具有优良的开放性和可扩展性,并提供了方便灵活的应用程序接口(API),从而使得C/C++程序员能够在各个级别上对Python解释器的功能进行扩展。在使用C/C++对Python进行功能扩展之前,必须首先掌握Python解释所提供的C语言接口。

2.1 Python对象(PyObject)

Python是一门面向对象的脚本语言,所有的对象在Python解释器中都被表示成PyObject,PyObject结构包含Python对象的所有成员指针,并且对Python对象的类型信息和引用计数进行维护。在进行Python的扩展编程时,一旦要在C或者C++中对Python对象进行处理,就意味着要维护一个PyObject结构。

在Python的C语言扩展接口中,大部分函数都有一个或者多个参数为PyObject指针类型,并且返回值也大都为PyObject指针。

2.2 引用计数

为了简化内存管理,Python通过引用计数机制实现了自动的垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。

下面的例子说明了Python解释器如何利用引用计数来对Pyhon对象进行管理:

例1:refcount.py
class refcount:
    # etc.
r1 = refcount() # 引用计数为1
r2 = r1         # 引用计数为2
del(r1)         # 引用计数为1
del(r2)         # 引用计数为0,删除对象

在C/C++中处理Python对象时,对引用计数进行正确的维护是一个关键问题,处理不好将很容易产生内存泄漏。Python的C语言接口提供了一些宏来对引用计数进行维护,最常见的是用Py_INCREF()来增加使Python对象的引用计数增1,用Py_DECREF()来使Python对象的引用计数减1。

2.3 数据类型

Python定义了六种数据类型:整型、浮点型、字符串、元组、列表和字典,在使用C语言对Python进行功能扩展时,首先要了解如何在C和Python的数据类型间进行转化。

2.3.1 整型、浮点型和字符串

在Python的C语言扩展中要用到整型、浮点型和字符串这三种数据类型时相对比较简单,只需要知道如何生成和维护它们就可以了。下面的例子给出了如何在C语言中使用Python的这三种数据类型:

例2:typeifs.c
// build an integer
PyObject* pInt = Py_BuildValue("i", 2003);
assert(PyInt_Check(pInt));
int i = PyInt_AsLong(pInt);
Py_DECREF(pInt);
// build a float
PyObject* pFloat = Py_BuildValue("f", 3.14f);
assert(PyFloat_Check(pFloat));
float f = PyFloat_AsDouble(pFloat);
Py_DECREF(pFloat);
// build a string
PyObject* pString = Py_BuildValue("s", "Python");
assert(PyString_Check(pString);
int nLen = PyString_Size(pString);
char* s = PyString_AsString(pString);
Py_DECREF(pString);

2.3.2 元组

Python语言中的元组是一个长度固定的数组,当Python解释器调用C语言扩展中的方法时,所有非关键字(non-keyword)参数都以元组方式进行传递。下面的例子示范了如何在C语言中使用Python的元组类型:

例3:typetuple.c
// create the tuple
PyObject* pTuple = PyTuple_New(3);
assert(PyTuple_Check(pTuple));
assert(PyTuple_Size(pTuple) == 3);
// set the item
PyTuple_SetItem(pTuple, 0, Py_BuildValue("i", 2003));
PyTuple_SetItem(pTuple, 1, Py_BuildValue("f", 3.14f));
PyTuple_SetItem(pTuple, 2, Py_BuildValue("s", "Python"));
// parse tuple items
int i;
float f;
char *s;
if (!PyArg_ParseTuple(pTuple, "ifs", &i, &f, &s))
    PyErr_SetString(PyExc_TypeError, "invalid parameter");
// cleanup
Py_DECREF(pTuple);

2.3.3 列表

Python语言中的列表是一个长度可变的数组,列表比元组更为灵活,使用列表可以对其存储的Python对象进行随机访问。下面的例子示范了如何在C语言中使用Python的列表类型:

例4:typelist.c
// create the list
PyObject* pList = PyList_New(3); // new reference
assert(PyList_Check(pList));
// set some initial values
for(int i = 0; i < 3; ++i)
    PyList_SetItem(pList, i, Py_BuildValue("i", i));
// insert an item
PyList_Insert(pList, 2, Py_BuildValue("s", "inserted"));
// append an item
PyList_Append(pList, Py_BuildValue("s", "appended"));
// sort the list
PyList_Sort(pList);
// reverse the list
PyList_Reverse(pList);
// fetch and manipulate a list slice
PyObject* pSlice = PyList_GetSlice(pList, 2, 4); // new reference
for(int j = 0; j < PyList_Size(pSlice); ++j) {
  PyObject *pValue = PyList_GetItem(pList, j);
  assert(pValue);
}
Py_DECREF(pSlice);
// cleanup
Py_DECREF(pList);

2.3.4 字典

Python语言中的字典是一个根据关键字进行访问的数据类型。下面的例子示范了如何在C语言中使用Python的字典类型:

例5:typedic.c
// create the dictionary
PyObject* pDict = PyDict_New(); // new reference
assert(PyDict_Check(pDict));
// add a few named values
PyDict_SetItemString(pDict, "first",
                     Py_BuildValue("i", 2003));
PyDict_SetItemString(pDict, "second",
                     Py_BuildValue("f", 3.14f));
// enumerate all named values
PyObject* pKeys = PyDict_Keys(); // new reference
for(int i = 0; i < PyList_Size(pKeys); ++i) {
  PyObject *pKey = PyList_GetItem(pKeys, i);
  PyObject *pValue = PyDict_GetItem(pDict, pKey);
  assert(pValue);
}
Py_DECREF(pKeys);
// remove a named value
PyDict_DelItemString(pDict, "second");
// cleanup
Py_DECREF(pDict);

回页首

三、Python的C语言扩展

3.1 模块封装

在了解了Python的C语言接口后,就可以利用Python解释器提供的这些接口来编写Python的C语言扩展,假设有如下一个C语言函数:

例6:example.c
int fact(int n)
{
  if (n <= 1)
    return 1;
  else
    return n * fact(n - 1);
}

该函数的功能是计算某个给定自然数的阶乘,如果想在Python解释器中调用该函数,则应该首先将其实现为Python中的一个模块,这需要编写相应的封装接口,如下所示:

例7: wrap.c
#include <Python.h>
PyObject* wrap_fact(PyObject* self, PyObject* args)
{
  int n, result;

  if (! PyArg_ParseTuple(args, "i:fact", &n))
    return NULL;
  result = fact(n);
  return Py_BuildValue("i", result);
}
static PyMethodDef exampleMethods[] =
{
  {"fact", wrap_fact, METH_VARARGS, "Caculate N!"},
  {NULL, NULL}
};
void initexample()
{
  PyObject* m;
  m = Py_InitModule("example", exampleMethods);
}

一个典型的Python扩展模块至少应该包含三个部分:导出函数、方法列表和初始化函数。

3.2 导出函数

要在Python解释器中使用C语言中的某个函数,首先要为其编写相应的导出函数,上述例子中的导出函数为wrap_fact。在Python的C语言扩展中,所有的导出函数都具有相同的函数原型:

PyObject* method(PyObject* self, PyObject* args);

该函数是Python解释器和C函数进行交互的接口,带有两个参数:self和args。参数self只在C函数被实现为内联方法(built-in method)时才被用到,通常该参数的值为空(NULL)。参数args中包含了Python解释器要传递给C函数的所有参数,通常使用Python的C语言扩展接口提供的函数PyArg_ParseTuple()来获得这些参数值。

所有的导出函数都返回一个PyObject指针,如果对应的C函数没有真正的返回值(即返回值类型为void),则应返回一个全局的None对象(Py_None),并将其引用计数增1,如下所示:

PyObject* method(PyObject *self, PyObject *args)
{
  Py_INCREF(Py_None);
  return Py_None;
}

3.3 方法列表

方法列表中给出了所有可以被Python解释器使用的方法,上述例子对应的方法列表为:

static PyMethodDef exampleMethods[] =
{
  {"fact", wrap_fact, METH_VARARGS, "Caculate N!"},
  {NULL, NULL}
};

方法列表中的每项由四个部分组成:方法名、导出函数、参数传递方式和方法描述。方法名是从Python解释器中调用该方法时所使用的名字。参数传递方式则规定了Python向C函数传递参数的具体形式,可选的两种方式是METH_VARARGS和METH_KEYWORDS,其中METH_VARARGS是参数传递的标准形式,它通过Python的元组在Python解释器和C函数之间传递参数,若采用METH_KEYWORD方式,则Python解释器和C函数之间将通过Python的字典类型在两者之间进行参数传递。

3.4 初始化函数

所有的Python扩展模块都必须要有一个初始化函数,以便Python解释器能够对模块进行正确的初始化。Python解释器规定所有的初始化函数的函数名都必须以init开头,并加上模块的名字。对于模块example来说,则相应的初始化函数为:

void initexample()
{
  PyObject* m;
  m = Py_InitModule("example", exampleMethods);
}

当Python解释器需要导入该模块时,将根据该模块的名称查找相应的初始化函数,一旦找到则调用该函数进行相应的初始化工作,初始化函数则通过调用Python的C语言扩展接口所提供的函数Py_InitModule(),来向Python解释器注册该模块中所有可以用到的方法。

3.5 编译链接

要在Python解释器中使用C语言编写的扩展模块,必须将其编译成动态链接库的形式。下面以RedHat Linux 8.0为例,介绍如何将C编写的Python扩展模块编译成动态链接库:

[[email protected] code]$ gcc -fpic -c -I/usr/include/python2.2                     -I /usr/lib/python2.2/config                     example.c wrapper.c
[[email protected] code]$ gcc -shared -o example.so example.o wrapper.o

3.6 引入Python解释器

当生成Python扩展模块的动态链接库后,就可以在Python解释器中使用该扩展模块了,与Python自带的模块一样,扩展模块也是通过import命令引入后再使用的,如下所示:

[[email protected] code]$ python
Python 2.2.1 (#1, Aug 30 2002, 12:15:30)
[GCC 3.2 20020822 (Red Hat Linux Rawhide 3.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.fact(4)
24
>>>

回页首

四、结束语

作为一门功能强大的脚本语言,Python将被更加广泛地应用于各个领域。为了克服脚本语言执行速度慢的问题,Python提供了相应的C语言扩展接口,通过将影响执行性能的关键代码用C语言实现,可以很大程度上提高用Python编写的脚本在运行时的速度,从而满足实际需要。

时间: 2024-10-10 11:23:33

windows 下 使用codeblocks 实现C语言对python的扩展的相关文章

在windows下用eclipse + pydev插件来配置python的开发环境

一.安装 python 可以到网上下个Windows版的python,官网为:https://www.python.org/downloads/下好后直接安装就ok了.最后记得配置一下环境变量,具体操作如下: 1)在计算机属性的环境变量配置中找到path, 2 )编辑path值,添加你安装的python路径, 3)检验python是否安装配置成功,打开cmd,输入python,如果出现以下界面,则说 明你的python安装成功了 二.安装eclipse插件 装插件的前提是先安装eclipse,e

Windows下使用Rtools编译R语言包

使用devtools安装github中的R源代码时,经常会出各种错误,索性搜了一下怎么在Windows下直接打包,网上的资料也是参差不齐,以下是自己验证通过的. 一.下载Rtools 下载地址:https://cran.r-project.org/bin/windows/Rtools/ 根据自己安装的R版本,下载兼容的Rtools即可,我下载的是Rtools35.exe 二.安装Rtools Windows下的安装都是傻瓜式的,一步步点确定即可,有两个地方需要注意: 2.1 安装路径 第一次安装

转 windows下安装pycharm并连接Linux的python环境

https://www.cnblogs.com/junxun/p/8287998.html 1. 下载安装Pycharm专业版 具体方法略.Pycharm5激活方法参考http://www.cnblogs.com/snsdzjlz320/p/7110186.html 2. 添加配置连接远程服务器 2.1  打开 PyCharm,依次点开 File  → Settings → Project scripts → Project Interpreter  选择“Add Remote” 2.2  点击

windows 下修改codeblocks颜色主题

从http://blog.sina.com.cn/s/blog_7d6898410101e620.html出转载. 1. 在C盘下搜索文件default.conf,用文本编辑器打开.然后用下面的代码替代. 2. 可能用新的界面风格会看不到光标,这个在CodeBlocks内修改, Settings->Configure editor->Margins and caret->Caret->Colour,选择一个可以辨识的颜色. 3. 修改字体,字体修改在 Settings->Co

在windows下配置apache以cgi方式支持python

Apache配置 在httpd.conf中查找DocumentRoot: 允许目录可以执行cgi: DocumentRoot  "D:\WWW" <Directory />     Options Indexes FollowSymLinks MultiViews ExecCGI     AllowOverride All     Order allow,deny     Allow from all     Require all granted </Directo

window环境下安装 pip 工具 【pip为Python的扩展管理工具】

Python有一些扩展管理工具,例如easy_install和pip工具,我推荐各位使用pip工具,因为pip工具具有很好的安装和卸载体验. 我们首先需要打开pip的官方网站, 下载必要的文件包,然后我们解压文件包,即可看到 setup.py ,最后我们把文件包复制到python安装目录下,在命令行模式下运行安装命令即可. 安装命令:setup.py install

【Python笔记】如何用C语言实现Python第三方扩展包

Python支持C/C++实现的第3方扩展包,在性能要求高的场合,这种特性显得尤其重要. 本文以实例说明定制Python扩展包的基本步骤. 1. 扩展包源码实现 按照Python官网教程Extending Python with C or C++说明的步骤,扩展模块的源文件实现如下: #include <Python.h> // forward declaration void initpyext(void); // self-defined error obj static PyObject

winsock教程- windows下的socket编程(c语言实现)

winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程 这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下代码片段只能运行在windows下.windows API中的socket编程部分叫做winsock. 你电脑上做出的任何网络通信背后基本上都有socket,它是一个网络的基本组成部分.举个例子说当你在浏览器键入www.google.com的时候,socket连接到google.com并且取回那个页面然后才

Windows下使用C语言实现2048

这是我之前写的一个小游戏,在windows下的Dev-C++中用C语言来实现的,通过不断的清屏,打印,清屏,打印来实现动态效果,不过功能不完善,有几个缺陷的地方. 实现效果(使用 w a s d 四个键来控制上下左右的移动) : 源代码(如果在Dev-C++中编译运行的时候报错,请将注释符号   //    换为  /**/ 来进行注释): #include <stdio.h> #include <stdlib.h> // for rand() and srand() and ex