设为首页 收藏本站
查看: 568|回复: 0

[经验分享] (Python编程)一个简单的C扩展模块

[复制链接]

尚未签到

发表于 2017-5-1 14:56:10 | 显示全部楼层 |阅读模式
Programming Python, 3rd Edition 翻译
最新版本见:http://wiki.woodpecker.org.cn/moin/PP3eD

22.4. A Simple C Extension Module

22.4. 一个简单的C扩展模块

At least that's the short story; we need to turn to some code to make this more concrete. C types generally export a C module with a constructor function. Because of that, and because they are simpler, let's start off by studying the basics of C module coding with a quick example.

简短的概览之后,我们需要用代码来更具体地展示C扩展。C类型一般导出一个C模块,其中有一个构造函数。那样很简单,因此,让我们用一个简例从编写C模块的基础开始学习。

As mentioned, when you add new or existing C components to Python, you need to code an interface ("glue") logic layer in C that handles cross-language dispatching and data translation. The C source file in Example 22-1 shows how to code one by hand. It implements a simple C extension module named hello for use in Python scripts, with a function named message that simply returns its input string argument with extra text prepended. Python scripts will call this function as usual, but this one is coded in C, not in Python.

如前所述,当你向Python添加新的或已有的C部件,你需要用C编写接口逻辑层(粘合层),来处理语言间的分派和数据翻译。例22-1的C语言源文件显示了如何对此进行手工编码。它实现了一个简单的C扩展模块hello,有一个函数message,简单地对输入串添加一些文本并返回,它可在Python脚本中使用。Python脚本像通常那样调用这个函数,但这个函数是用C写的,而不是Python.

Example 22-1. PP3E/Integrate/Extend/Hello/hello.c
DSC0000.gif DSC0001.gif /**//********************************************************************
DSC0002.gif *AsimpleCextensionmoduleforPython,called"hello";compile
*thisintoa".so"onpythonpath,importandcallhello.message;
DSC0003.gif *******************************************************************
*/
DSC0004.gif
#include
<Python.h>
#include
<string.h>

/**//*modulefunctions*/
staticPyObject*/**//*returnsobject*/
message(PyObject
*self,PyObject*args)/**//*selfunusedinmodules*/
...{/**//*argsfromPythoncall*/
char*fromPython,result[64];
DSC0005.gif DSC0006.gif
if(!PyArg_Parse(args,"(s)",&fromPython))/**//*convertPython->C*/
returnNULL;/**//*null=raiseexception*/
else...{
strcpy(result,
"Hello,");/**//*buildupCstring*/
strcat(result,fromPython);
/**//*addpassedPythonstring*/
returnPy_BuildValue("s",result);/**//*convertC->Python*/
DSC0007.gif }

}


/**//*registrationtable*/
staticstructPyMethodDefhello_methods[]=...{
...{"message",message,1},/**//*methodname,Cfuncptr,always-tuple*/
...{NULL,NULL}/**//*endoftablemarker*/
}
;

/**//*moduleinitializer*/
voidinithello()/**//*calledonfirstimport*/
...{/**//*namemattersifloadeddynamically*/
(
void)Py_InitModule("hello",hello_methods);/**//*modname,tableptr*/
}





Ultimately, Python code will call this C file's message function, passing in a string object and getting back a new string object. First, though, it has to be somehow linked into the Python interpreter. To use this C file in a Python script, compile it into a dynamically loadable object file (e.g., hello.so on Linux, hello.dll under Cygwin on Windows) with a makefile like the one listed in Example 22-2, and drop the resulting object file into a directory listed on your module import search path exactly as though it were a .py or .pyc file.

最终Python代码将调用这个C文件中的message函数,传入一个字符串对象并返回一个新的字符串对象。但是,它首先必须以某种方式连接到Python解释器。为了在Python脚本中使用这个C文件,可使用类似例22-2所列的make文件,将它编译成动态装载的目标文件(例如,Linux上的hello.so,Windows上的Cygwin下的hello.dll),并将结果目标文件放入你的导入模块搜索路径,就像它是一个.py或.pyc文件。

Example 22-2. PP3E/Integrate/Extend/Hello/makefile.hello
#############################################################
# Compile hello.c into a shareable object file on Cygwin,
# to be loaded dynamically when first imported by Python.
#############################################################

PYLIB = /usr/bin
PYINC = /usr/include/python2.4

hello.dll: hello.c
gcc hello.c -g -I$(PYINC) -shared -L$(PYLIB) -lpython2.4 -o hello.dll

clean:
rm -f hello.dll core



This is a Cygwin makefile that uses gcc to compile our C code; other platforms are analogous but will vary. As mentioned in Chapter 5 in the sidebar "Forking on Windows with Cygwin," Cygwin provides a Unix-like environment and libraries on Windows. To work along with the examples here, either see http://www.cygwin.com for download details or change the makefiles listed per your compiler and platform requirements. Be sure to include the path to Python's install directory with -I flags to access Python include (a.k.a. header) files, as well as the path to the Python binary library file with -L flags, if needed.

这是一个Cygwin make文件,用gcc作编译器;在其它平台会有不同,但是类似。在第5章的补充栏“在Windows上用Cygwin来分支进程”中提过,Cygwin在Windows上提供了一个类Unix的环境和库。要让这里的例子工作,要么查看http://www.cygwin.com上的下载详情,要么按你的平台和编译器的要求更改make文件。注意要用-I参数包含Python的安装路径,这样才能找到Python包含文件,也叫头文件,必要时还要用-L参数指出Python的二进制库文件的路径。

Now, to use the makefile in Example 22-2 to build the extension module in Example 22-1, simply type a standard make command at your shell (the Cygwin shell is used here):

现在,在你的shell界面简单地敲入标准make命令,用例22-2的make文件来构建例22-1的扩展模块,本例中使用的是Cygwin shell:

.../PP3E/Integrate/Extend/Hello$ make -f makefile.hello
gcc hello.c -g -I/usr/include/python2.4 -shared
-L/usr/bin -lpython2.4 -o hello.dll



This generates a shareable object filea .dll under Cygwin on Windows. When compiled this way, Python automatically loads and links the C module when it is first imported by a Python script. At import time, the .dll binary library file will be located in a directory on the Python import search path, just like a .py file. Because Python always searches the current working directory on imports, this chapter's examples will run from the directory you compile them in (.) without any file copies or moves. In larger systems, you will generally place compiled extensions in a directory listed in PYTHONPATH or .pth files instead.

这样会生成一个共享目标文件,在Windows的Cygwin上是一个.dll文件。这样编译后,Python会在脚本第一次导入时,自动装载和链接这个C模块。当导入时,将会在Python的导入搜索路径中查找该.dll二进制库文件,就像一个.py文件。因为Python导入时总是搜索当前工作目录,本章的例子将不进行复制或称动,而是在你编译的当前目录(.)下运行。而在大型系统中,你一般会将编译的扩展模块放在PYTHONPATH或.pth文件所列目录下。

Finally, to call the C function from a Python program, simply import the module hello and call its hello.message function with a string; you'll get back a normal Python string:

最后,在Python程序中调用C函数,只需导入hello模块并调用hello.message函数;你将得到一个Python串返回值。

.../PP3E/Integrate/Extend/Hello$ python
>>> import hello # import a C module
>>> hello.message('world') # call a C function
'Hello, world'
>>> hello.message('extending')
'Hello, extending'



And that's ityou've just called an integrated C module's function from Python. The most important thing to notice here is that the C function looks exactly as if it were coded in Python. Python callers send and receive normal string objects from the call; the Python interpreter handles routing calls to the C function, and the C function itself handles Python/C data conversion chores.

这就成了,你刚才已经在Python中调用了一个集成的C模块的函数。着重要注意的是,这里C函数看起来完全像是用Python编写的。Python调用者传入和接收了一个普通的字符串对象;Python解译器将调用发送给C函数,C函数本身处理了Python/C的数据转换。

In fact, there is little to distinguish hello as a C extension module at all, apart from its filename. Python code imports the module and fetches its attributes as if it had been written in Python. C extension modules even respond to dir calls as usual and have the standard module and filename attributes (though the filename doesn't end in a .py or .pyc this time around):

实际上,除了文件名之外,很难分辨出hello是一个C扩展模块。Python代码导入模块并获取它的属性,就像它是Python写的一样。C扩展模块甚至像通常那样响应dir调用,并有标准的模块和文件名属性(尽管这里的文件名不是.py或.pyc结尾)。

>>> dir(hello) # C module attributes
['_ _doc_ _', '_ _file_ _', '_ _name_ _', 'message']

>>> hello._ _name_ _, hello._ _file_ _
('hello', 'hello.dll')

>>> hello.message # a C function object
<built-in function message>
>>> hello # a C module object
<module 'hello' from 'hello.dll'>



Like any module in Python, you can also access the C extension from a script file. The Python file in Example 22-3, for instance, imports and uses the C extension module.

你也可以在脚本文件中像Python模块一样使用C扩展模块。例22-3的Python文件导入并使用了C扩展模块。

Example 22-3. PP3E/Integrate/Extend/Hello/hellouse.py
importhello

printhello.message('C')
printhello.message('module'+hello.__file__)

foriinrange(3):
printhello.message(str(i))




Run this script as any otherwhen the script first imports the module hello, Python automatically finds the C module's .dll object file in a directory on the module search path and links it into the process dynamically. All of this script's output represents strings returned from the C function in the file hello.c:

像其它脚本那样运行这个脚本。当第一次导入模块hello时,Python自动在模块搜索路径中找到C模块的.dll目标文件,并将它动态链接到进程内。脚本的输出就是hello.c文件的C函数的返回串。

.../PP3E/Integrate/Extend/Hello$ python hellouse.py
Hello, C
Hello, module /cygdrive/c/.../PP3E/Integrate/Extend/Hello/hello.dll
Hello, 0
Hello, 1
Hello, 2



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-371734-1-1.html 上篇帖子: python-gearman之多个GearmanServer问题 下篇帖子: 『原创』Python的GUI开发:小试wxPython(上)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表