Python移植到Linux移植,无ctype



所有能被整合或导入到其它python脚本嘚代码都可以被称为扩展。可以用Python来写扩展也可以用C和C++之类的编译型的语言来写扩展。Python在设计之初就考虑到要让模块的导入机制足够抽象抽象到让使用模块的代码无法了解到模块的具体实现细节。Python的可扩展性具有的优点:方便为语言增加新功能、具有可定制性、代码鈳以实现复用等
(1)创建应用程序代码

       上述代码中有两个函数,一个是递归求阶乘的函数fac();另一个reverse()函数实现了一个简单的字符串反转算法其主要目的是修改传入的字符串,使其内容完全反转但不需要申请内存后反着复制的方法。

(2)用样板来包装代码

代码与Python解释器之間进行交互所必不可少的一部分样板主要分为4步:a、包含Python的头文件;b、为每个模块的每一个函数增加一个型如PyObject* Module_func()的包装函数;c、为每个模塊增加一个型如PyMethodDef ModuleMethods[]的数组;d、增加模块初始化函数void initModule()。

一个 Python的整数参数把它转为C的整数,然后调用C的fac()函数得到一个整型的返回值,最后把這个返回值转为Python的整型数做为整个函数调用的结果返回回去其他两个包装函数Extest_doppel()和Extest_test()类似。

的用法跟C的sscanf函数很像都接受一个字符串流,并根据一个指定的格式字符串进行解析把结果放入到相应的指针所指的变量中去,它们的返回值为1表示解析成功返回值为0表示失败

Py_BuildValue的用法跟sprintf很像,把所有的参数按格式字符串所指定的格式转换成一个Python的对象


PyArg_ParseTupleAndKeywords()函数来分析命名参数的话,还需要让这个标志常量与METH_KEYWORDS常量进行逻輯与运算常量 数组最后用两个NULL来表示函数信息列表的结束。

Extension()第一个参数是(完整的)扩展的名字如果模块是包的一部分的话,还要加上用'.'汾隔的完整的包的名字上述的扩展是独立的,所以名字只要写"Extest"就行;sources参数是所有源代码的文件列表只有一个文件Extest2.c。setup需要两个参数:一個名字参数表示要编译哪个内容;另一个列表参数列出要编译的对象上述要编译的是一个扩展,故把ext_modules参数的值设为扩展模块的列表


(5)引用计数和线程安全

,保证了运行和非运行时的安全性由这些宏包裹的代码将会允许其他线程的运行。


需要的时候还可以改一改只偠不改变接口。缺点是C++的程序一旦编译好了再改就没那么方便了。

//进行初始化它会载入Python的内建模块并添加系统路 //径到模块搜索路径中。这个函数没有返回值检查系统 // 检查初始化是否成功 //把输入的字符串作为Python代码直接运行,返回0 //表示成功-1表示有错。大多时候错误都是洇为字符串 // 找出函数名为add的函数 // 把C++的变量转换成一个Python对象当需要从 // C++传递变量到Python时,就会使用这个函数此函数 // 有点类似C的printf,但格式不同常用的格式有 // s 表示字符串, // i 表示整型变量 // f 表示浮点数, //下面这段是查找函数foo 并执行foo


(1)Python和C/C++的相互调用仅是测试代码具体的项目开发還得参考Python的API文档。
(2)两者交互C++可为Python编写扩展模块,Python也可为C++提供脚本接口更加方便于实际应用。
(3)若有不足请留言,在此先感谢!

最近看了《Gray hat python》一书这才知道为什么python是黑客必学的编程语言。通过python的ctypes模块可以直接调用动态链接库中的导出函数,而且甚至可以直接在python中构建出复杂的C结构体!!!使嘚python也具备了底层内存操作的能力再配合python本身强大的表达能力,能不让人激动么

之前为了在python中调用动态链接库导出的函数,你需要自行解析出这些导出函数的地址而现在ctypes库会替我们完成这个麻烦的过程,大大方便了我们直接在python中调用C函数的能力

ctypes模块中有三种不同的动態链接库加载方式:cdll, windll, oledll。不同之处在于链接库中的函数所遵从的函数调用方式(calling convention)以及返回方式有所不同

cdll用于加载遵循cdecl标准函数调用约定嘚链接库。windll则用于加载遵循stdcall调用约定的动态链接库oledll与windll完全相同,只是会默认其载入的函数会统一返回一个Windows HRESULT错误编码

先复习一下有关函數调用约定的知识:函数调用约定指的是函数参数入栈的顺序、哪些参数入栈、哪些通过寄存器传值、函数返回时栈帧的回收方式(是由調用者负责清理,还是被调用者清理)、函数名称的修饰方法等等基本上我们最常见的调用约定就是cdecl和stdcall两种。在《程序员的自我修养--链接、装载与库》一书的第10章有对函数调用约定的更详细介绍

cdecl规定函数参数列表以从右到左的方式入栈,且由函数的调用者负责清除栈帧仩的参数stdcall的参数入栈方式与cdecl一致,但函数返回时是由被调用者自己负责清理栈帧而且stdcall是Win32 API函数所使用的调用约定。OK就这么多,够了

測试一下在Linux移植平台和Windows平台下通过ctypes模块导入C库中函数的小例子:

 
 

可以看到动态链接库中的printf被直接导入到python中来调用了。

那么在python中怎么表示C的類型?不用担心下面这张表就能搞定。

有了这个映射关系多复杂的C类型也能在python中表达出来。

而在python中同等的定义为:注意一下python中定义数組的方式

 

测试一下这个例子,在python中定义一个联合体为其赋值,再分别访问其成员

 

我要回帖

更多关于 Linux移植 的文章

 

随机推荐