设为首页 收藏本站
查看: 785|回复: 0

[经验分享] Python调用Linux c库:ctypes初学体验

[复制链接]

尚未签到

发表于 2018-8-12 10:04:01 | 显示全部楼层 |阅读模式
  我在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 typec_bool_Boolbool (1)c_charchar1-character stringc_wcharwchar_t1-character unicode stringc_bytecharint/longc_ubyteunsignedcharint/longc_shortshortint/longc_ushortunsignedshortint/longc_intintint/longc_uintunsignedintint/longc_longlongint/longc_ulongunsignedlongint/longc_longlong__int64 or longlongint/longc_ulonglongunsigned__int64 or unsignedlonglongint/longc_floatfloatfloatc_doubledoublefloatc_longdoublelongdoublefloatc_char_pchar* (NUL terminated)string or Nonec_wchar_pwchar_t* (NUL terminated)unicode or Nonec_void_pvoid*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,>
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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-550493-1-1.html 上篇帖子: Python之threading模块简单使用 下篇帖子: python添加tab,自动补齐
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表