专栏首页python3Python调用Linux c库:cty

Python调用Linux c库:cty

   我在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 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:

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”。

   好了,关于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 "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 条评论
登录 后参与评论

相关文章

  • 探索支付宝小程序:如何与前端工程结合?

    小程序的技术栈中,最吸引人的点莫过小程序专属流量入口了,例如小程序收藏、小程序搜索。小程序作为一个全新的生态,上手开发会和一般的前端技术栈,有很大的差别。那么小...

    极乐君
  • Elasticsearch 一把梭,用起来再说?!

    场景1:我们这边开发只要work,管他wildcard,能模糊就好,管他内存,windows size死命地设,不管多少页都让它翻。

    zhisheng
  • 腾讯云主机Python3环境安装PySp

    利用腾讯云服务器我们可以玩好多的技术,前面的我给大家分享的大多与网站和一些服务有关,今天我给大家分享有关腾讯云主机Python3环境安装PySpider爬虫框架...

    用户2398817
  • 借助云开发10行代码生成小程序码,可以微信扫码快速进入指定小程序页

    我们生成的小程序码指定的页面,必须是你小程序已经发布,如果小程序还没有发布,获取小程序码绑定的页面不存在,扫码后就会出现以下错误

    编程小石头
  • Python3 logging tips

    用户2398817
  • 大数据-Hive内置函数与自定义函数

    cwl_java
  • uCharts实现一个叠堆柱状图

    在uni-app里面会使用到统计图,和echarts类似,也有自己的官方文档可以作参考,开发考勤的app项目的时候遇到了一个叠堆柱状图,统计每天正常,迟到,缺勤...

    祈澈菇凉
  • 使用腾讯云云点播对视频进行HLS加密

    加密并不是百分百不会泄露,只是增加直接获取被加密资源的代价,别人录屏等等也是可以的,防不胜防

    沈唁
  • Python3网络爬虫实战-12、部署相

    如果想要大规模抓取数据,那么一定会用到分布式爬虫,对于分布式爬虫来说,我们一定需要多台主机,每台主机多个爬虫任务,但是源代码其实只有一份。那么我们需要做的就是将...

    用户2398817
  • Python-Django

    一般在urls.py中配置url,在models.py中配置model,在views.py中配置View。

    用户2398817

扫码关注云+社区

领取腾讯云代金券