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

[经验分享] python嵌入C++------ boost.python如何在C++中调用含有不定长参数tuple变量和关键字参数dict变量的函数

[复制链接]

尚未签到

发表于 2015-4-24 08:39:36 | 显示全部楼层 |阅读模式
  这个问题是在我尝试利用pygraphviz嵌入我的C++代码绘制二叉树的时候发现的.找了半天资料,这里我把几种常用的C++调用
  PYTHON利用 boost.python 的方法作一个总结,希望能让别人少走弯路,因为有些内容还找不到中文文档,虽然都不难但是开始摸索

  还是费时间的.

  我个人认为boost.python真的是非常的COOL,基本上不需要去学习那个看了就头大用着也不方便的python c api了,唯一的缺点
  是目前相关的资料太少,甚至官网上也解释不够详细.

  前面我写了一篇python嵌入c++的入门文章包括安装和环境配置,介绍了如何利用 boost.python方便的传递C++代码中的参数,调用 python函数.boost.python入门教程 ----python 嵌入c++
  这个boost.python官网上的tourial也有介绍.
  


  • 首先第一种常用方式是 python::boost::exec


#include
using namespace boost::python;
  //引入python解释器
  Py_Initialize();
  //引入__main__ 作用域
  object main_module = import("__main__");
  object main_namespace = main_module.attr("__dict__");
exec("print('Hello world!')", main_namespace);
//exec + python command string + 作用域


  • 第二种方法是利用boost::python::object对象
  第一种方法虽然很好但是不方便和C++交互数据,如传递C++中的数据作为参数给python函数,以及C++接受python执行函数后
  的返回值. 那么怎么用object调用python函数呢,很简单看下面的代码就了解了.

  我在simple.py中定义了函数
  def foo(int i = 3):
  return i + 2008

  这样一个简单的函数, 通过将simple.py利用boost::python::exec_file将其引入到__main__作用域,我们在__main__.__dict__

  也就是main_namespace中取到命名为foo的函数对象,并将其转换成boost::python::object使用. 这里我们给这个object
  同样命名为foo,调用foo(5)即调用python 函数foo(5)返回2013,注意在C++环境中要用extract将这个值取到.



object simple = exec_file("simple.py",main_namespace, main_namespace);
  object foo = main_namespace["foo"];
  int val = extract(foo(5));
  cout  G=AGraph()
    >>> G.add_node('a')
    >>> G.nodes()
    ['a']
    >>> G.add_node(1) # will be converted to a string
    >>> G.nodes()
    ['a', '1']
    Attributes can be added to nodes on creation
    >>> G.add_node(2,color='red')

  
  该参数列表由一个普通参数和一个关键字参数构成,你可能会想上面的几种operator()的重载函数中没有这种形式啊?
  没有关系,解决的办法是将普通参数在这里当作tuple看待,而且你只能这么做:)否则运行通不过的!

  具体的办法是如果你的函数有n 个普通参数在关键字参数前面那么你就生成并传递一个有n个元素组成的tuple,

  如果是形如foo(**kargs)这样的函数,那么你也需要先传递一个空tuple,

    void sort(args_proxy const &args, kwds_proxy const &kwds);
    x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));   
// 等价于 Python 调用 x.sort(reverse=true)
  好了下面看一下我调用add_node的代码,注意add_node(1, color='red')表示生成一个node,它的关键字是1,而颜色是红色,

  我也可能会调用 add _node(2, lable='abc')表示该节点关键字是2,而它将会被输出显示的标志是abc.


void print(std::string result = "huff_tree.dot") {
    using namespace boost::python;   //for tree printing
    Py_Initialize();
    object main_module = import("__main__");
    object main_namespace = main_module.attr("__dict__");
    exec("import pygraphviz as pgv", main_namespace);
    exec("tree_graph = pgv.AGraph(directed=True,strict=True)", main_namespace);
    object tree_graph = main_namespace["tree_graph"];
   
    tree_graph.attr("add_node")(*make_tuple(1), **dict(make_tuple(make_tuple("label", "Jordan"))));
   
    exec("tree_graph.graph_attr['epsilon']='0.001'", main_namespace);
    exec("tree_graph.layout('dot')", main_namespace);
    exec("tree_graph.write('huff_tree.dot')", main_namespace);
  }
  
  恩,看下生成的huff_tree.dot文件,node 的 key 是1, label是Jordan,完全正确:)

  strict digraph {
        graph [bb="0,0,70,36",
                epsilon="0.001"
        ];
        node [label="\N"];
        1        [height="0.50",
                label=Jordan,
                pos="35,18",
                width="0.97"];
}
  图片显示如下:   

DSC0000.jpg
  关于上面代码dict(make_tuple(make_tuple()))的解释:
  其实是这样的对这样一个tuple(tuple,tuple) 如 ((1,2),(3,4)) 执行dict操作得到 {1:2,3:4}
  即dict(make_tuple(make_tuple(1,2),make_tuple(3,4))) =  {1:2, 3:4}  
  而上面的例子women其实就是dict(make_tuple(make_tuple(1,2))这样里面只有一个tuple的特例。
  

运维网声明 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-60140-1-1.html 上篇帖子: 深入Python(三) 下篇帖子: python的图形化界面(1)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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