Python调用Linux c库:ctypes初学体验
2014-04-30 16:54
330 查看
我在http://jlnsqt.blog.51cto.com/2212965/1405052这篇博客中讲述了匹配URL的一个算法,因项目需要将其封装为动态库,并让python组调用,所以研究了一下ctypes,感觉超级棒,必须记录下来。
首先介绍一下我的动态库接口。
动态库结构体:
这里不再给出生成动态库方法和各个接口函数的定义,只介绍如何在python中调用。这里假设我动态库的名称为“liburlwhitelist.so”,动态库和python文件在同一目录,或者再引用动态库的时候用绝对路径。
开始使用ctypes之前,介绍一下ctypes的类型对照:
首先导入ctypes:
导入库,可用绝对路径:
引入接口函数,并对接口函数属性进行设置。
InitUrlWhiteList.restype设置函数的返回类型,因为ctypes默认的返回类型时C int,我这里还是指出,便于统一和减少出错。
使用部分例子:
好了,关于ctypes,先介绍到这里,更详细的请参考官方文档:https://docs.python.org/2/library/ctypes.html。详细代码如下:
首先介绍一下我的动态库接口。
动态库结构体:
typedef struct _whitelist_tree_node_ { uint8_t white_type; //匹配白名单是否结束,代表下一步执行的动作 uint8_t child_count; //该节点的子节点个数 uint8_t child_order[MAX_CHILDS_NUM]; //子节点在childs的位置(起始1) struct _whitelist_tree_node_ *childs; //子节点数组 } whitelist_tree_node; typedef struct _whitelist_tree_ { whitelist_tree_node *root; //根节点 unsigned int whitelist_count; //URL白名单个数 } whitelist_tree, *PUrlWhiteListControl; 函数接口: /** * [InitUrlWhiteList根据配置文件读取数据库中的URL白名单,并初始化到内存中] * @param ini_file [配置文件路径,一般若无特殊数据库配置可为NULL] * @param p_control [查询控制器,用完需要关掉] * @return [0: success, other: failure code] */ int InitUrlWhiteList(const char *ini_file, PUrlWhiteListControl *p_control); /** * [SearchUrlWhiteList 查询URL是否在白名单中] * @param url [待查URL] * @param p_control [查询控制器] * @return [0: find, < 0: run failure code, > 0: not find] */ int SearchUrlWhiteList(const char *url, PUrlWhiteListControl p_control); /** * [CloseUrlWhiteList 关闭初始化的查询控制器] * @param control [控制器] */ void CloseUrlWhiteList(PUrlWhiteListControl p_control);
这里不再给出生成动态库方法和各个接口函数的定义,只介绍如何在python中调用。这里假设我动态库的名称为“liburlwhitelist.so”,动态库和python文件在同一目录,或者再引用动态库的时候用绝对路径。
开始使用ctypes之前,介绍一下ctypes的类型对照:
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 | unsignedchar | int/long |
c_short | short | int/long |
c_ushort | unsignedshort | int/long |
c_int | int | int/long |
c_uint | unsignedint | int/long |
c_long | long | int/long |
c_ulong | unsignedlong | int/long |
c_longlong | __int64 or longlong | int/long |
c_ulonglong | unsigned__int64 or unsignedlonglong | int/long |
c_float | float | float |
c_double | double | float |
c_longdouble | longdouble | 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 |
from ctypes import *定义最大子节点个数,也即静态数组的大小。
#max child node number MAX_NODE_CHILD_NUM = 46下面就是重点了,需要用python模拟出Linux C的结构体来。
#define tree node class whitelist_tree_node(Structure): pass whitelist_tree_node._fields_ = [ ("white_type", c_ubyte), ("child_count", c_ubyte), ("child_order", c_ubyte * MAX_NODE_CHILD_NUM), ("childs", POINTER(whitelist_tree_node)) ] #define tree class whitelist_tree(Structure): pass whitelist_tree._fields_ = [ ("root", POINTER(whitelist_tree_node)), ("whitelist_count", c_uint) ] #define query url whitelist control PUrlWhiteListControl = POINTER(whitelist_tree)为了定义节点指向自己的指针,这里必须先用pass定义一个空的对象,否则会出现“NameError: name 'whitelist_tree_node' is not defined”的错误。取类型的指针用POINTER()函数,而取变量对象的指针用pointer()函数,注意区分。
导入库,可用绝对路径:
#load library url_whitelist_lib = cdll.LoadLibrary("./liburlwhitelist.so")
引入接口函数,并对接口函数属性进行设置。
#define init function InitUrlWhiteList= url_whitelist_lib.InitUrlWhiteList #define argument types InitUrlWhiteList.argtypes = [POINTER(PUrlWhiteListControl)] #define return types. By default functions are assumed to return the C int type InitUrlWhiteList.restype = c_int #define search function SearchUrlWhiteList = url_whitelist_lib.SearchUrlWhiteList SearchUrlWhiteList.argtypes = [c_char_p, PUrlWhiteListControl] SearchUrlWhiteList.restype = c_int #define close function CloseUrlWhiteList = url_whitelist_lib.CloseUrlWhiteList CloseUrlWhiteList.argtypes = [PUrlWhiteListControl] CloseUrlWhiteList.restype = None定义每个函数第一行“
InitUrlWhiteList
=
url_whitelist_lib.InitUrlWhiteList”是为了减少函数调用。InitUrlWhiteList.argtypes设置函数的参数,为了更好的调用,减少出错。
InitUrlWhiteList.restype设置函数的返回类型,因为ctypes默认的返回类型时C int,我这里还是指出,便于统一和减少出错。
使用部分例子:
p_control = PUrlWhiteListControl()这里有三个地方需要注意。一、None变量即是C中NULL。二:InitUrlWhiteList参数,因其第二个参数为PUrlWhiteListControl的指针,所以这里用pointer()函数,当然也可用byref()函数,但是在官方文档中指出:
ret_code = InitUrlWhiteList(None, pointer(p_control))
if ret_code != 0:
print "InitUrlWhiteListerror code: %d" % ret_code
else:
print "init url whitelist num: %u" % p_control.contents.whitelist_count
The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself所以这里我们还是用pointer()函数好。三、因PUrlWhiteListControl本身是一个指针,要访问他的内容需要用contents方法。如“p_control.contents.whitelist_count”。
好了,关于ctypes,先介绍到这里,更详细的请参考官方文档:https://docs.python.org/2/library/ctypes.html。详细代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: sqt
# @Email: qingtao_shang@vulnhunt.com
# @Date: 2014-04-30 09:57:37
# @Desc: Python测试URL白名单动态库
# @Last Modified by: sqt
# @Last Modified time: 2014-04-30 13:30:17
from ctypes import *
#max child node number MAX_NODE_CHILD_NUM = 46
#define tree node
class whitelist_tree_node(Structure):
pass
whitelist_tree_node._fields_ = [
("white_type", c_ubyte),
("child_count", c_ubyte),
("child_order", c_ubyte * MAX_NODE_CHILD_NUM),
("childs", POINTER(whitelist_tree_node))
]
#define tree
class whitelist_tree(Structure):
pass
whitelist_tree._fields_ = [
("root", POINTER(whitelist_tree_node)),
("whitelist_count", c_uint)
]
#define query url whitelist control
PUrlWhiteListControl = POINTER(whitelist_tree)
#load library url_whitelist_lib = cdll.LoadLibrary("./liburlwhitelist.so")
#simple call function name
#define init function InitUrlWhiteList= url_whitelist_lib.InitUrlWhiteList #define argument types InitUrlWhiteList.argtypes = [POINTER(PUrlWhiteListControl)] #define return types. By default functions are assumed to return the C int type InitUrlWhiteList.restype = c_int #define search function SearchUrlWhiteList = url_whitelist_lib.SearchUrlWhiteList SearchUrlWhiteList.argtypes = [c_char_p, PUrlWhiteListControl] SearchUrlWhiteList.restype = c_int #define close function CloseUrlWhiteList = url_whitelist_lib.CloseUrlWhiteList CloseUrlWhiteList.argtypes = [PUrlWhiteListControl] CloseUrlWhiteList.restype = None
#sample
if __name__ == "__main__":
p_control = PUrlWhiteListControl()
ret_code = InitUrlWhiteList(None, pointer(p_control))
if ret_code != 0:
print "InitUrlWhiteListerror code: %d" % ret_code
else:
print "init url whitelist num: %u" % p_control.contents.whitelist_count
url = ""
while 1:
url = raw_input("Input url or exit:")
if url == "q" or url == "exit":
break
find_code = SearchUrlWhiteList(url, p_control)
if find_code == 0:
print "url: %s find." % url
else:
print "url: %s not find." % url
CloseUrlWhiteList(p_control)
del p_control
相关文章推荐
- 模拟xcopy的函数
- api流程控制1——ctypes,调用C的动态库
- py,pyc,pyo的区别
- py批量图片抓取
- Centos6.2 安装Python2.7.x 版本
- py属性方法和函数
- python操作文件写入内容
- py_web---github代码库使用
- day 5 【错题】日志模块碰到的奇妙问题
- day 4 模块
- day 4 序列化反序列化
- day4 装饰器
- py练习
- pycharm安装packages以及使用模板
- 升级Linux下的Python遇到问题
- mail.py
- python_django urlpatterns
- py_Django之表单
- py_Django的管理界面常见组件
- py_Django的管理界面