在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 函数的更多相关文章

  1. (原)python使用ctypes调用C/C++接口

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6135514.html 参考网址: https://docs.python.org/2/library/ ...

  2. python学习:调用其他函数

    vim wc.py   #!/usr/bin/python   def wordCount(s):     chars = len(s)     words = len(s.split())     ...

  3. python网络编程调用recv函数完整接收数据的三种方法

    最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...

  4. python调用C函数

    python 与 c可以相互调用,在做后台服务时底层服务用C/C++编写,通过python调用C库可以极大的提高开发效率. 下面对几种调用方式举例说明 1 python通过指针传递浮点型数组给C函数 ...

  5. python中使用ctypes调用MinGW生成的动态链接库(dll)

    关于gcc编译dll的我就不说了,网上举例一大堆,下面以g++为例. 假设有一个test.cpp文件如下: extern "C" { __declspec(dllexport) d ...

  6. Python 调用C函数

    /******************************************************************** * Python 调用C函数 * 说明: * Tony在处理 ...

  7. 使用ctypes调用系统C API函数需要注意的问题,函数参数中有指针或结构体的情况下最好不要修改argtypes

    有人向我反应,在代码里同时用我的python模块uiautomation和其它另一个模块后,脚本运行时会报错,但单独使用任意一个模块时都是正常的,没有错误.issue链接 我用一个例子来演示下这个问题 ...

  8. Python利用ctypes实现C库函数调用

    0X00 ctypes 是强大的,使用它我们就能够调 用动态链接库中函数,同时创建各种复杂的 C 数据类型和底层操作函数.使得python也具备了底层内存操作的能力,再配合python本身强大的表达能 ...

  9. python学习笔记10(函数一): 函数使用、调用、返回值

    一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明和函数定义可以出现在不同的文件中,比如C语言),但是在Python中,函数声明和函数定义是视为一体的.在Py ...

随机推荐

  1. Android设计和开发系列第二篇:Action Bar(Develop—Training)

    Adding the Action Bar GET STARTED DEPENDENCIES AND PREREQUISITES Android 2.1 or higher YOU SHOULD AL ...

  2. Win8设计——现代设计,可使你的应用脱颖而出的元素

    Microsoft 设计准则 Windows 在现代设计方面遥遥领先.它采用了“真实数字”原则并从瑞士风格和交通枢纽的寻路系统中汲取灵感. 阅读详细信息 设计元素 动态磁贴 动态磁贴向你提供了一个独特 ...

  3. CSS3 渐变效果

    CSS3 渐变效果 background-image: -moz-linear-gradient(top, #8fa1ff, #3757fa); /* Firefox */ background-im ...

  4. 题目1016:火星A+B(进制新问题)

    题目链接:http://ac.jobdu.com/problem.php?pid=1016 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  5. LeetCode 81 Search in Rotated Sorted Array II(循环有序数组中的查找问题)

    题目链接:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/#/description   姊妹篇:http://www. ...

  6. sencha touch 在线实战培训 第一期 第五节

    2014.1.6晚上8点准时开的课 本期培训一共八节,前三堂免费,后面的课程需要付费才可以观看. 本节内容:             实现皮肤自定义样式的修改 css相关理论: 重写官方样式,美化ap ...

  7. JVM常用工具使用之jmap

    一.参考链接 https://www.cnblogs.com/yjd_hycf_space/p/7753847.html 二.个人的总结 一般我习惯使用 jmap -dump:live,format= ...

  8. 供安全工程师实用的SOC模型

    一.背景 如今,安全概念满天飞,什么安全运营中心(SOC).威胁情报(TI).态势感知等等不一而足,这些概念及其背后代表的安全思想都很好,不过很多产品为了迎合国内的工作汇报都做成了很多Dashboar ...

  9. nodeJS删除文件

    var fs = require("fs"); var path = require("path"); deleteFolderRecursive = func ...

  10. Html5游戏框架createJs组件--EaselJS(二)绘图类graphics

    有端友问我是否有文档,有确实有,但没有中文的,只有英文的,先提供浏览地址供大家参考学习createJs英文文档.                        EaselJS其实主要就是createJ ...