前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python调用Linux c库:cty

Python调用Linux c库:cty

作者头像
py3study
发布2020-01-09 16:48:16
1.3K0
发布2020-01-09 16:48:16
举报
文章被收录于专栏:python3

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

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

   动态库结构体:

代码语言:javascript
复制
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

   首先导入ctypes:

代码语言:javascript
复制
from ctypes import *

   定义最大子节点个数,也即静态数组的大小。    

代码语言:javascript
复制
#max child node number
MAX_NODE_CHILD_NUM = 46

   下面就是重点了,需要用python模拟出Linux C的结构体来。

代码语言:javascript
复制
#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()函数,注意区分。

   导入库,可用绝对路径:    

代码语言:javascript
复制
#load library
url_whitelist_lib = cdll.LoadLibrary("./liburlwhitelist.so")

   引入接口函数,并对接口函数属性进行设置。    

代码语言:javascript
复制
#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,我这里还是指出,便于统一和减少出错。

   使用部分例子:

代码语言:javascript
复制
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()函数,但是在官方文档中指出:

代码语言:javascript
复制
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。详细代码如下:

代码语言:javascript
复制
#!/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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档