#ifndef __FFPYTHON_H_
#define __FFPYTHON_H_
#include
#include
#include
using namespace std;
#include "pyops_base.h"
#include "pyops_for_embed.h"
#include "pyops_for_extend.h"
class ffpython_t
{
struct reg_info_t
{
reg_info_t():args_num(0),option_args_num(0),func_addr(0){}
int args_num;
int option_args_num;
long func_addr;
PyCFunction func;
string func_name;
string func_impl_name;
string doc;
string doc_impl;
};
public:
ffpython_t();
~ffpython_t();
static int init_py();
static int final_py();
static int add_path(const string& path_);
static int run_string(const string& py_);
static int reload(const string& py_name_);
static int load(const string& py_name_);
//! 将需要注册的函数、类型注册到python虚拟机
int init(const string& mod_name_, string doc_ = "");
//! 注册static function,
template
ffpython_t& reg(T func_, const string& func_name_, string doc_ = "")
{
reg_info_t tmp;
tmp.args_num = pyext_func_traits_t::args_num();
tmp.option_args_num = pyext_func_traits_t::option_args_num();
tmp.func = (PyCFunction)pyext_func_traits_t::pyfunc;
tmp.func_name= func_name_;
tmp.func_impl_name = func_name_ + "_internal_";
tmp.doc = doc_;
tmp.doc_impl = string("internal use, please call ") + func_name_;
tmp.func_addr= (long)func_;
m_func_info.push_back(tmp);
return *this;
}
//! 注册c++ class
template
pyclass_regigster_tool_t& reg_class(const string& class_name_, string doc_ = "", string inherit_name_ = "")
{
if (pyclass_base_info_t::pytype_info.class_name.empty() == false)
throw runtime_error("this type has been registed");
pyclass_base_info_t::pytype_info.class_name = class_name_;
//pyclass_base_info_t::pytype_info.mod_name = m_mod_name;
pyclass_base_info_t::pytype_info.total_args_num = pyext_func_traits_t::args_num() +
pyext_func_traits_t::option_args_num();
pyclass_regigster_tool_t tmp;
tmp.class_name = class_name_;
tmp.class_real_name = class_name_ + "_internal_";
tmp.inherit_name = inherit_name_;
tmp.doc = doc_;
tmp.dector = (destructor)pyclass_base_info_t::free_obj;
tmp.init = (initproc)pyclass_ctor_tool_t::init_obj;
tmp.ctor = pyclass_base_info_t::alloc_obj;
tmp.type_size = sizeof(typename pyclass_base_info_t::obj_data_t);
tmp.args_num = pyext_func_traits_t::args_num();
tmp.option_args_num = pyext_func_traits_t::option_args_num();
tmp.static_pytype_info = &(pyclass_base_info_t::pytype_info);
//! 注册析构函数,python若不调用析构函数,当对象被gc时自动调用
tmp.delete_func = (PyCFunction)pyclass_base_info_t::release;
m_all_pyclass.push_back(tmp);
return m_all_pyclass.back();
}
//! 调用python函数,最多支持9个参数
template
RET_V call(const string& mod_name_, const string& func_)
{
pycall_arg_t args(0);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1)
{
pycall_arg_t args(1);
args.add(a1);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2)
{
pycall_arg_t args(2);
args.add(a1).add(a2);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3)
{
pycall_arg_t args(3);
args.add(a1).add(a2).add(a3);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4)
{
pycall_arg_t args(4);
args.add(a1).add(a2).add(a3).add(a4);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5)
{
pycall_arg_t args(5);
args.add(a1).add(a2).add(a3).add(a4).add(a5);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6)
{
pycall_arg_t args(6);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6,const ARG7& a7)
{
pycall_arg_t args(7);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8)
{
pycall_arg_t args(8);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
template
RET_V call(const string& mod_name_, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8, const ARG9& a9)
{
pycall_arg_t args(9);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8).add(a9);
pytype_tool_impl_t pyret;
return pycall_t::call(mod_name_, func_, args, pyret);
}
//!call python class method begin******************************************************************
template
RET_V obj_call(PyObject* pobj, const string& func_)
{
pycall_arg_t args(0);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1)
{
pycall_arg_t args(1);
args.add(a1);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2)
{
pycall_arg_t args(2);
args.add(a1).add(a2);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3)
{
pycall_arg_t args(3);
args.add(a1).add(a2).add(a3);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4)
{
pycall_arg_t args(4);
args.add(a1).add(a2).add(a3).add(a4);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5)
{
pycall_arg_t args(5);
args.add(a1).add(a2).add(a3).add(a4).add(a5);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6)
{
pycall_arg_t args(6);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6,const ARG7& a7)
{
pycall_arg_t args(7);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8)
{
pycall_arg_t args(8);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
template
RET_V obj_call(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8, const ARG9& a9)
{
pycall_arg_t args(9);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8).add(a9);
pytype_tool_impl_t pyret;
return pycall_t::call_obj_method(pobj, func_, args, pyret);
}
//!call python class method end******************************************************************
//!call python lambad function begin ############################################################
template
RET_V call_lambda(PyObject* pobj)
{
pycall_arg_t args(0);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1)
{
pycall_arg_t args(1);
args.add(a1);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2)
{
pycall_arg_t args(2);
args.add(a1).add(a2);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3)
{
pycall_arg_t args(3);
args.add(a1).add(a2).add(a3);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4)
{
pycall_arg_t args(4);
args.add(a1).add(a2).add(a3).add(a4);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5)
{
pycall_arg_t args(5);
args.add(a1).add(a2).add(a3).add(a4).add(a5);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6)
{
pycall_arg_t args(6);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5,const ARG6& a6,const ARG7& a7)
{
pycall_arg_t args(7);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8)
{
pycall_arg_t args(8);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
template
RET_V call_lambda(PyObject* pobj, const string& func_, const ARG1& a1, const ARG2& a2, const ARG3& a3, const ARG4& a4,
const ARG5& a5, const ARG6& a6, const ARG7& a7, const ARG8& a8, const ARG9& a9)
{
pycall_arg_t args(9);
args.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8).add(a9);
pytype_tool_impl_t pyret;
return pycall_t::call_lambda(pobj, args, pyret);
}
//!call python lambad function ennd ############################################################
template
RET_V get_global_var(const string& mod_name_, const string& var_name_)
{
PyObject *pName = NULL, *pModule = NULL;
string err_msg;
pName = PyString_FromString(mod_name_.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (NULL == pModule)
{
pyops_t::traceback(err_msg);
throw runtime_error(err_msg.c_str());
}
pytype_tool_impl_t pyret;
PyObject *pvalue = PyObject_GetAttrString(pModule, var_name_.c_str());
Py_DECREF(pModule);
if (!pvalue)
{
pyops_t::traceback(err_msg);
throw runtime_error(err_msg.c_str());
}
if (pyret.parse_value(pvalue))
{
Py_XDECREF(pvalue);
throw runtime_error("type invalid");
}
Py_XDECREF(pvalue);
return pyret.get_value();
}
template
int set_global_var(const string& mod_name_, const string& var_name_, const T& val_)
{
PyObject *pName = NULL, *pModule = NULL;
string err_msg;
pName = PyString_FromString(mod_name_.c_str());
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (NULL == pModule)
{
pyops_t::traceback(err_msg);
throw runtime_error(err_msg.c_str());
}
PyObject* pval = pytype_traits_t::pyobj_from_cppobj(val_);
int ret = PyObject_SetAttrString(pModule, var_name_.c_str(), pval);
Py_DECREF(pModule);
return ret != -1? 0: -1;
}
template
RET_V getattr(PyObject* pModule, const string& var_name_)
{
string err_msg;
if (NULL == pModule)
{
throw runtime_error("getattr object ptr null");
}
pytype_tool_impl_t pyret;
PyObject *pvalue = PyObject_GetAttrString(pModule, var_name_.c_str());
if (!pvalue)
{
pyops_t::traceback(err_msg);
throw runtime_error(err_msg.c_str());
}
if (pyret.parse_value(pvalue))
{
Py_XDECREF(pvalue);
throw runtime_error("type invalid");
}
Py_XDECREF(pvalue);
return pyret.get_value();
}
void cache_pyobject(PyObject* pobj)
{
m_cache_pyobject.push_back(pobj);
}
void clear_cache_pyobject()
{
if (Py_IsInitialized())
{
for (size_t i = 0; i < m_cache_pyobject.size(); ++i)
{
Py_XDECREF(m_cache_pyobject[i]);
}
m_cache_pyobject.clear();
}
}
private:
PyObject* init_method();
int init_pyclass(PyObject* m);
bool is_method_exist(const vector<:method_info_t>& src_, const string& new_);
bool is_property_exist(const vector<:property_info_t>& src_, const string& new_);
pyclass_regigster_tool_t* get_pyclass_info_by_name(const string& name_);
private:
string m_mod_name;
string m_mod_doc;
vector m_pymethod_defs;
vector m_func_info;
//! reg class
vector m_all_pyclass;
//! cache some pyobject for optimize
vector m_cache_pyobject;
};
#endif