ctypes python_Python调用Linux c库:ctypes初学体验

我在http://jlnsqt.blog.51cto.com/2212965/1405052这篇博客中讲述了匹配URL的一个算法,因项目需要将其封装为动态库,并让python组调用,所以研究了一下ctypes,感觉超级棒,必须记录下来。

首先介绍一下我的动态库接口。

动态库结构体: 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 typeC typePython type_Boolbool (1)

char1-character string

wchar_t1-character unicode string

charint/long

unsignedcharint/long

shortint/long

unsignedshortint/long

intint/long

unsignedintint/long

longint/long

unsignedlongint/long

__int64 or longlongint/long

unsigned__int64 or unsignedlonglongint/long

floatfloat

doublefloat

longdoublefloat

char* (NUL terminated)string or None

wchar_t* (NUL terminated)unicode or None

void*int/long or None

首先导入ctypes:

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()

ret_code = InitUrlWhiteList(None, pointer(p_control))

if ret_code != 0:

print "InitUrlWhiteList error code: %d" % ret_code

else:

print "init url whitelist num: %u" % p_control.contents.whitelist_count

这里有三个地方需要注意。一、None变量即是C中NULL。二:InitUrlWhiteList参数,因其第二个参数为PUrlWhiteListControl的指针,所以这里用pointer()函数,当然也可用byref()函数,但是在官方文档中指出: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”。

#!/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 "InitUrlWhiteList error 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值