Python 使用ctypes调用 C 函数
在python中通过ctypes可以直接调用c的函数,非常简单易用
下面就一步一步解释用法吧,以Linux为例讲解。
1, 首先确定你的python支持不支持ctypes
python2.7以后ctypes已经是标配了,2.4以后的版本得自己装下ctypes
2,加载动态库
两种加载方式
>>> from ctypes import *
>>> libc = cdll . LoadLibrary ( "libc.so.6" )
>>> libc.printf("%d",2)
>>> from ctypes import *
>>> libc = CDLL ( "libc.so.6" )
>>> libc.printf("%d",2)
3, 调用系统函数
上面的例子已经调用了系统函数printf,这里再给几个其他例子
>>> from ctypes import *
>>> libc = CDLL ( "libc.so.6" )
>>> print libc . time ( None )
1308019893
>>> print libc.atoi("234")
234
4,ctypes 数据类型和 C数据类型 对照表
ctypes type | C type | Python type |
---|---|---|
c_bool | _Bool | bool (1) |
c_char | char | 1-character string |
c_wchar | wchar_t | 1-character unicode string |
c_byte | char | int/long |
c_ubyte | unsigned char | int/long |
c_short | short | int/long |
c_ushort | unsigned short | int/long |
c_int | int | int/long |
c_uint | unsigned int | int/long |
c_long | long | int/long |
c_ulong | unsigned long | int/long |
c_longlong | __int64 or long long | int/long |
c_ulonglong | unsigned __int64 or unsigned long long | int/long |
c_float | float | float |
c_double | double | float |
c_longdouble | long double | float |
c_char_p | char * (NUL terminated) | string or None |
c_wchar_p | wchar_t * (NUL terminated) | unicode or None |
c_void_p | void * | int/long or None |
这些数据都可以用一个默认值进行创建
>>> c_int()
c_long(0)
>>> c_char_p("Hello, World")
c_char_p('Hello, World')
>>> c_ushort(-3)
c_ushort(65533)
>>>
这些数据也可以被改变:
>>> i = c_int(42)
>>> print i
c_long(42)
>>> print i.value
42
>>> i.value = -99
>>> print i.value
-99
>>>
赋值给 c_char_p,c_wchar_p,c_void_p
只改变他们指向的内存地址,而不是改变内存的内容
>>> s = "Hello, World"
>>> c_s = c_char_p(s)
>>> print c_s
c_char_p('Hello, World')
>>> c_s.value = "Hi, there"
>>> print c_s
c_char_p('Hi, there')
>>> print s # first string is unchanged
Hello, World
>>>
如果需要可改变内容的字符串,需要使用 create_string_buffer()
>>> from ctypes import *
>>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes
>>> print sizeof(p), repr(p.raw)
3 '/x00/x00/x00'
>>> p = create_string_buffer("Hello") # create a buffer containing a NUL terminated string
>>> print sizeof(p), repr(p.raw)
6 'Hello/x00'
>>> print repr(p.value)
'Hello'
>>> p = create_string_buffer("Hello", 10) # create a 10 byte buffer
>>> print sizeof(p), repr(p.raw)
10 'Hello/x00/x00/x00/x00/x00'
>>> p.value = "Hi"
>>> print sizeof(p), repr(p.raw)
10 'Hi/x00lo/x00/x00/x00/x00/x00'
>>>
5,函数返回类型
函数默认返回 C int 类型,如果需要返回其他类型,需要设置函数的 restype 属性
>>> strchr = libc.strchr
>>> strchr("abcdef", ord("d")) # doctest: +SKIP
8059983
>>> strchr.restype = c_char_p # c_char_p is a pointer to a string
>>> strchr("abcdef", ord("d"))
'def'
>>> print strchr("abcdef", ord("x"))
None
>>>
6,传递指针或者引用
很多情况下 C 函数需要传递指针或者引用,ctypes也完美的支持这一点
byref() 用来传递引用参数,pointer() 函数也可以完成同样的工作,但pointer()会创建一个实际的指针对象,如果你不需要一个指针对象,
用byref()会快很多
>>> i = c_int()
>>> f = c_float()
>>> s = create_string_buffer('/000' * 32)
>>> print i.value, f.value, repr(s.value)
0 0.0 ''
>>> libc.sscanf("1 3.14 Hello", "%d %f %s",... byref(i), byref(f), s)
3
>>> print i.value, f.value, repr(s.value)
1 3.1400001049 'Hello'
>>>
7,结构体和联合
结构体和联合必须从 Structure 和 Union 继承,子类必须定义
_fields_ 属性,_fields_ 属性必须是一个2元组的列表,
包括一个field名字和field的类型
field类型 必须是一个ctypes的类型例如 c_int, 或者其他继承自ctypes的类型,结构体,联合,数组,指针。
下面的例子演示一个 POINT结构体,包括 field X,Y
>>> from ctypes import *
>>> class POINT(Structure):.
_fields_ = [("x", c_int),
("y", c_int)]
>>> point = POINT(10, 20)
>>> print point.x, point.y
10 20
>>> point = POINT(y=5)
>>> print point.x, point.y
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1
, in ?
ValueError
: too many initializers
>>>
一个复杂点的例子,field类型也是一个结构体
>>> class RECT(Structure):
... _fields_ = [("upperleft", POINT),
... ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print rc.upperleft.x, rc.upperleft.y
0 5
>>> print rc.lowerright.x, rc.lowerright.y
0 0
>>>
多种方式进行初始化
>>> r = RECT(POINT(1, 2), POINT(3, 4))
>>> r = RECT((1, 2), (3, 4))
8,数组
数组定义很简单
定义一个有10个POINT元素的数组
TenPointsArrayType = POINT * 10
初始化和使用数组:
>>> from ctypes import *
>>> TenIntegers = c_int * 10
>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> print ii
<c_long_Array_10 object at 0x...>
>>> for i in ii: print i,
...
1 2 3 4 5 6 7 8 9 10
>>>
9,指针
pointer() 函数可以创建一个指针
Pointer实例有一个 contents属性 返回指针指向的对象
>>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>> pi.contents
c_long(42)
可以改变指针指向的内容
>>> i = c_int(99)
>>> pi.contents = i
>>> pi.contents
c_long(99)
>>>
可以按数组方式访问:
>>> pi[0]
99
>>>
按数组方式改变值
>>> print i
c_long(99)
>>> pi[0] = 22
>>> print i
c_long(22)
>>>
以上都是ctypes的基本用法,对普通的开发人员来说,基本够用了
更详细的说明请参考:http://docs.python.org/library/ctypes.html
Python 使用ctypes调用 C 函数的更多相关文章
- (原)python使用ctypes调用C/C++接口
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6135514.html 参考网址: https://docs.python.org/2/library/ ...
- python学习:调用其他函数
vim wc.py #!/usr/bin/python def wordCount(s): chars = len(s) words = len(s.split()) ...
- python网络编程调用recv函数完整接收数据的三种方法
最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...
- python调用C函数
python 与 c可以相互调用,在做后台服务时底层服务用C/C++编写,通过python调用C库可以极大的提高开发效率. 下面对几种调用方式举例说明 1 python通过指针传递浮点型数组给C函数 ...
- python中使用ctypes调用MinGW生成的动态链接库(dll)
关于gcc编译dll的我就不说了,网上举例一大堆,下面以g++为例. 假设有一个test.cpp文件如下: extern "C" { __declspec(dllexport) d ...
- Python 调用C函数
/******************************************************************** * Python 调用C函数 * 说明: * Tony在处理 ...
- 使用ctypes调用系统C API函数需要注意的问题,函数参数中有指针或结构体的情况下最好不要修改argtypes
有人向我反应,在代码里同时用我的python模块uiautomation和其它另一个模块后,脚本运行时会报错,但单独使用任意一个模块时都是正常的,没有错误.issue链接 我用一个例子来演示下这个问题 ...
- Python利用ctypes实现C库函数调用
0X00 ctypes 是强大的,使用它我们就能够调 用动态链接库中函数,同时创建各种复杂的 C 数据类型和底层操作函数.使得python也具备了底层内存操作的能力,再配合python本身强大的表达能 ...
- python学习笔记10(函数一): 函数使用、调用、返回值
一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明和函数定义可以出现在不同的文件中,比如C语言),但是在Python中,函数声明和函数定义是视为一体的.在Py ...
随机推荐
- SQL Server设置登录验证模式
我们在安装SQL Server的时候可以设置“混合验证模式”,既可以使用windows身份验证登录,也可以使用SQL Server身份验证登录. 如果我们在安装的时候并未设置"混合验证模式& ...
- Express+Less+Gulp配置高效率开发环境
版权声明:本文由金朝麟原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/627049001486519548 来源:腾云阁 h ...
- 题目1016:火星A+B(进制新问题)
题目链接:http://ac.jobdu.com/problem.php?pid=1016 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- LeetCode 11 Container With Most Water(分支判断问题)
题目链接 https://leetcode.com/problems/container-with-most-water/?tab=Description Problem: 已知n条垂直于x轴的线 ...
- iOS 循环引用 委托 (实例说明)
如何避免循环引用造成的内存泄漏呢: 以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时 ...
- C++和Java中的静态Static用法
C++和Java中都有的一个静态关键字Static,可以放在类中的变量或者函数之前,就成了静态变量或者静态函数. 静态变量又分为静态全局变量和静态局部变量,可参见网上大神总结的C++全局变量,局部变量 ...
- Centos清除IP
要把配置好的ip清除掉,可以使用以下命令: ip addr flush dev eth0 如果系统中没有ip这个命令,可以使用更简单的: ifconfig eth0 0.0.0.0 可以用于PPTP拨 ...
- HOJ 2133&POJ 2964 Tourist(动态规划)
Tourist Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1503 Accepted: 617 Description A ...
- OpenCV学习笔记之课后习题练习2-5
5.对练习4中的代码进行修改,参考例2-3,给程序加入滚动条,使得用户可以动态调节缩放比例,缩放比例的取值为2-8之间.可以跳过写入磁盘操作,但是必须将变换结果显示在窗口中. 参考博文:blog.cs ...
- HDU 1222 - Wolf and Rabbit & HDU 1108 - [最大公约数&最小公倍数]
水题,只是想借此记一下gcd函数的模板 #include<cstdio> int gcd(int m,int n){return n?gcd(n,m%n):m;} int main() { ...