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!!
目录
相关文章
|
传感器 安全 算法
【C语言】C语言可以做什么?
C语言因其高效、灵活和低级控制能力,被广泛应用于各个领域,从基础设施和科学计算到金融、交通和机器人技术。它在许多关键应用中展示了其不可替代的价值和广泛的适用性。
920 2
|
算法 C语言
factorial函数c语言
C语言中实现阶乘函数提供了直接循环和递归两种思路,各有优劣。循环实现更适用于大规模数值,避免了栈溢出风险;而递归实现则在代码简洁度上占优,但需警惕深度递归带来的潜在问题。在实际开发中,根据具体需求与环境选择合适的实现方式至关重要。
609 0
|
传感器 自动驾驶 安全
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
无人驾驶汽车对人民的出行方式和生活方式产生了深远的影响
|
JavaScript API
Antd——如何给树形控件增加编辑删除
Antd——如何给树形控件增加编辑删除
595 0
|
弹性计算 运维 监控
阿里云轻量应用服务器和ECS有什么区别?如何选择?十大区别对比
阿里云服务器分为轻量应用服务器和云服务器ECS,轻量是在云服务器ECS基础上推出的轻量级云服务器,轻量应用服务器是一款可快速搭建且易于管理的轻量级云服务器,提供基于单台服务器的应用部署、安全管理、可视化运维监控等服务,使用门槛低。轻量应用服务器结合WordPress等应用镜像,可以快速搭建所需Web环境
1574 0
阿里云轻量应用服务器和ECS有什么区别?如何选择?十大区别对比
|
监控 安全 网络安全
什么是HW,企业如何进行HW保障?
护网行动是一种积极、有效的网络安全防护措施,它通过实战化的演练来提升网络安全防护能力,确保网络系统的安全和稳定。
1977 0
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp微信小程序的二手物品交易平台的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的二手物品交易平台的详细设计和实现
238 0
|
安全 Linux 网络安全
2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-A-CTF攻击与防御
模块C和D是CTF夺旗比赛,分别聚焦攻击和防御。攻击者需利用各种漏洞(如命令注入、文件上传、远程代码执行等)攻陷靶机,获取权限,但禁止攻击裁判服务器。防御者则需检测并加固堡垒服务器,确保服务可用性,发现并修补同样类型的漏洞。比赛分数依据靶机的flag值和加固报告,强调不提供补时。操作环境涉及Windows和Linux,选手需使用谷歌浏览器登录。注意提交清晰的截图和PDF报告至U盘。
407 0
|
项目管理 PHP 前端开发
推荐5款开源的协同办公软件
国内外开源的协同办公软件
17584 0
|
存储 关系型数据库 MySQL
【MySQL】事务日志 undo log 详解
Redo log是事务持久性的保证,Undo log是事务原子性的保证。在事务中更新数据的前置操作其实就是要写入Undo log。事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如: 情况一:事务执行过程中可能遇到各种错误,比如服务器本身的错误,操作系统错误,甚至是突然断电导致的错误。 情况二:程序员可以在事务执行过程中手动输入ROLLBACK语句结束当前事务的执行以上情况出现,我们需要把数据改回原先的样子,这个过程称之为回滚,这样就可以造成一个假象:这个事务看起来什么都没做,所以符合原子性要求每当我们要对一条记录做改动。