Embeding Python & Extending Python with FFPython

简介: Introduction ffpython is a C++ lib, which is to simplify tasks that embed Python and extend Python. As the author, I am a developer for MMO server.

Introduction

ffpython is a C++ lib, which is to simplify tasks that embed Python and extend Python. As the author, I am a developer for MMO server. Mainly I use C++ to implement part that needs to response user's requests in realtime, while other logic part that needs to be modified frequently is implemented by Python. Python makes it possible to reload our part of the server when the server is running. Python is so easy that even my colleague with no programing skills can implement some npc script. When I was first in charge of integrating Python runtime interpreter to our C++ server, I used Boost.python. Somehow Boost.python helped me solve most problems about Python API especially parts of Python reference. But Boost.python is not perfect.

  • When exception happens while invoking python function by boost.python, boost.python doesn't provide interface to fetch traceback information.
  • Boost python is a big lib to some extent. Someone will find it much difficult who just wants to try to experience how embedding Python works.
  • Boost.pyhon supports badly to extend python by using C++ static function and class in runtime. Boost.python recommends to use dynamic library to extending python.
  • Someone who wants to learn example code using Python API will find it difficult to understand well boost.python codes, in my opinion.
  • If you have the need to convert data between C++ STL container and python object builtin, you have to implement these codes yourself, while Python reference is so annoying.

FFPython

Firstly, I implemented it just for converting data between C++ STL container and python object. Some of my colleagues have writes a lot of code using Python API directly. But there is some trap in some Python API even engineers who have a lot of experience using Python may have lost. PyDict_SetItem will auto increase reference key and value arguments, but other Python builtin structure API like PyTuple_SetItem will not increase reference the argument. It will cause memory leak. So I wanted to wrap operations about converting data between C++ STL container and Python builtin structure. Finally, I found some elegant ways to wrap embedding Python and extending Python by C++ template skills. So that is how FFPyhton was born.

Embedding Python

Sometimes I think it's easier to show codes to readers here. ^_^. But it will be forbidden by administrator if I post lots of code. O(n_n)O~. So see code files or Github.

When Embedding Python, such functions are most needed.

  • Fetch global variable of python script(or module). This happens when you use Python script as config files.
  • Call python function in script. That is the most useful interface. Two parts of it are important.
    1. It should be supported to use C++ builtin type and C++ STL container as argument.
    2. It should be supported to convert returned value of Python builtin types (like list, tuple, dict, string...) to C++ builtin types.
  • Fetch exception information when exception happens, especially traceback information. Because of feature of dynamic type, exception regularly happens even in online server, let alone debugging time. ffpython will throw std exception when Python exception happens. So it is much easier to print or log traceback info by outputexception.what() .
  • ffpython support nine arguments.
  • ffpython implemented by C++ template to wrap Python API. It is easy to understand how it works if you see the code.
 printf("sys.version=%s\n", 
ffpython.get_global_var<string>("sys", "version").c_str()); 

int a1 = 100; float a2 = 3.14f; string a3 = "OhWell";
ffpython.call<void>("fftest", "test_base", a1, a2, a3);
vector<int> a1;a1.push_back(100);a1.push_back(200);
list<string> a2; a2.push_back("Oh");a2.push_back("Nice");
vector<list<string> > a3;a3.push_back(a2);
ffpython.call<bool>("fftest", "test_stl", a1, a2, a3);
typedef map<string, list<vector<int> > > ret_t;
ret_t val = ffpython.call<ret_t>("fftest", "test_return_stl");

 

Extending Python

ffpython recommends to register C++ function/class in runtime. It works to design and develop MMO game server. So that is common use for me. There are some key points when embedding Python.

  • ffpython supports to register C++ static function. C++ builtin types and STL container can be as arguments.
  • C++ class can be registered to Python.

Register C++ static function, all base type supported. Arg num can be nine.

static int print_val(int a1, float a2, const string& a3, const vector<double>& a4)
{
    printf("%s[%d,%f,%s,%d]\n", __FUNCTION__, a1, a2, a3.c_str(), a4.size());
    return 0;
}

ffpython_t ffpython;//("ext1");
ffpython.reg(&print_val, "print_val");
ffpython.init("ext1"); 

 

Register C++ class, Python can use it just like builtin types.

class foo_t{

public:
    foo_t(int v_):m_value(v_){
    printf("%s\n", __FUNCTION__);
    }
    virtual ~foo_t(){
        printf("%s\n", __FUNCTION__);
    } 
    int get_value() const { return m_value; }
    void set_value(int v_) { m_value = v_; }
    void test_stl(map<string, list<int> >& v_) 
    {
        printf("%s\n", __FUNCTION__);
    }
    int m_value;
};
class dumy_t: public foo_t
{
public:
    dumy_t(int v_):foo_t(v_)
    {
        printf("%s\n", __FUNCTION__);
    }
    ~dumy_t()
    {
        printf("%s\n", __FUNCTION__);
    }
    void dump() 
    {
        printf("%s\n", __FUNCTION__);
    }
};
static foo_t* obj_test(dumy_t* p)
{
    printf("%s\n", __FUNCTION__);
    return p;
}
void test_register_base_class(ffpython_t& ffpython)
{
    ffpython.reg_class<foo_t, PYCTOR(int)>("foo_t")
            .reg(&foo_t::get_value, "get_value")
            .reg(&foo_t::set_value, "set_value")
            .reg(&foo_t::test_stl, "test_stl")
            .reg_property(&foo_t::m_value, "m_value");
};   

 

Summary

  • ffpython only one implements head file, it is easy to integrate to project.
  • ffpython is simply wrap for Python API, so it is efficient.
  • github: https://github.com/fanchy/ffpython
  • python2.5 python2.6 python2.7, win / linux
  • python3.x is being developed, but unfortunately, Python3.x API is so different to python2.x, even different between python3.2 and python3.3, Headache!!
目录
相关文章
|
10月前
|
传感器 安全 算法
【C语言】C语言可以做什么?
C语言因其高效、灵活和低级控制能力,被广泛应用于各个领域,从基础设施和科学计算到金融、交通和机器人技术。它在许多关键应用中展示了其不可替代的价值和广泛的适用性。
513 2
|
8月前
|
数据采集 监控 安全
电商数据接口实战:全量获取店铺商品的技术方案与进阶策略
该文档介绍了通过官方API获取店铺全量商品数据的技术实现与应用场景。主要涵盖四大方面:业务场景(如店铺运营监控、竞品分析等)、技术实现流程(包括环境准备、接口调用和分页策略)、数据结构解析与治理(如响应结构、数据处理建议),以及企业级解决方案设计(架构设计、性能优化、数据更新策略)。同时,强调了合规与安全实践,并提供了典型问题的解决方案。适用于电商中台项目,支持日均亿级商品数据处理。
|
传感器 自动驾驶 安全
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
|
存储 分布式计算 Hadoop
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
ClickHouse是一款高性能的列式存储OLAP数据库,由俄罗斯的Yandex公司开发,用于在线分析处理(OLAP)。它提供秒级大数据查询,适用于商业智能、广告流量等领域。ClickHouse速度快的原因包括列式存储、数据压缩、向量化执行和多线程分布式处理。然而,它不支持事务,不适合OLTP操作。相比Hadoop生态中的查询引擎,ClickHouse在大量数据查询上表现出色。一系列的文章详细介绍了ClickHouse的各个方面,包括安装、表引擎和使用场景。
2174 2
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
|
安全 关系型数据库 数据库
上新|阿里云RDS PostgreSQL支持PG 16版本,AliPG提供丰富自研能力
AliPG在社区版16.0的基础上,在安全、成本、可运维性等多个方面做了提升,丰富的内核/插件特性支持,满足业务场景的需求
|
弹性计算 运维 监控
阿里云轻量应用服务器和ECS有什么区别?如何选择?十大区别对比
阿里云服务器分为轻量应用服务器和云服务器ECS,轻量是在云服务器ECS基础上推出的轻量级云服务器,轻量应用服务器是一款可快速搭建且易于管理的轻量级云服务器,提供基于单台服务器的应用部署、安全管理、可视化运维监控等服务,使用门槛低。轻量应用服务器结合WordPress等应用镜像,可以快速搭建所需Web环境
1538 0
阿里云轻量应用服务器和ECS有什么区别?如何选择?十大区别对比
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp微信小程序的二手物品交易平台的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的二手物品交易平台的详细设计和实现
170 0
|
监控 安全 网络安全
什么是HW,企业如何进行HW保障?
护网行动是一种积极、有效的网络安全防护措施,它通过实战化的演练来提升网络安全防护能力,确保网络系统的安全和稳定。
1873 0
|
安全 Linux 网络安全
2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-A-CTF攻击与防御
模块C和D是CTF夺旗比赛,分别聚焦攻击和防御。攻击者需利用各种漏洞(如命令注入、文件上传、远程代码执行等)攻陷靶机,获取权限,但禁止攻击裁判服务器。防御者则需检测并加固堡垒服务器,确保服务可用性,发现并修补同样类型的漏洞。比赛分数依据靶机的flag值和加固报告,强调不提供补时。操作环境涉及Windows和Linux,选手需使用谷歌浏览器登录。注意提交清晰的截图和PDF报告至U盘。
351 0
|
存储 缓存 监控
ES写入过程和写入原理调优及如何保证数据的写一致性(下)
ES写入过程和写入原理调优及如何保证数据的写一致性(下)