使用C++扩展Python2

使用C++扩展Python的时候主要实现:

* 将C++中的函数引入到Python中去

* 以及将C++中的类引入到Python中去

 

同时还涉及到:

* 返回值扩展类型

* 参数检测

* 异常处理

* 软件程序编译以及发布

 

大部分是模式化编程,套模本即可。

#ifndef _DM_PYX_ACTION_HPP
#define _DM_PYX_ACTION_HPP

#include <Python.h>
#include <dm/scada/scada.hpp>

namespace dm{
namespace pyx{

struct SAction{
    PyObject_HEAD
    int idx;
    const dm::scada::SActionInfo* pInfo;
};

extern PyTypeObject* TypeAction;

int init_action( PyObject* module );

};
};

#endif

定义了一个扩展类的头文件。

因为需要在其他扩展中使用该扩展类,作为数据返回,或者作为参数引用。

这里使用的是C++的命名空间写法。

实现的部分,基本上就是套模本了。

#include "action.hpp"
#include <dm/scada/actionmgr.hpp>
#include <dm/scada/actiondescmgr.hpp>

#include <dm/os/log/logger.hpp>

static const char* logModule = "action.pyx.dm";

namespace dm{
namespace pyx{

typedef SAction LObject;

static void l_dealloc( LObject* self,PyObject* args ){
	Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject* l_new( PyTypeObject *type, PyObject *args, PyObject *kwds ){
	return type->tp_alloc(type,0);
}

static PyObject * l_repr(LObject * self){
    const dm::scada::SActionInfo* pInfo = self->pInfo;

    return PyString_FromFormat("Action:{idx:%d,id:%d,name:%s,desc:%s,invOff:%d,off:%d,on:%d,invOn:%d,level:%d,save:%d,report:%d}",
        self->idx,
        self->pInfo->id,self->pInfo->name.c_str(),self->pInfo->desc.c_str(),
        self->pInfo->desc_invOff,self->pInfo->desc_off,self->pInfo->desc_on,self->pInfo->desc_invOn,
        self->pInfo->level,self->pInfo->isFlagSave(),self->pInfo->isFlagReportTimed());
}

static int l_init(LObject *self, PyObject *args, PyObject *kwds)
{
    // 传递的参数是索引号
    if (!_PyArg_NoKeywords("Action()", kwds)){
        log().error(STATICMODULE "构造函数错误");
        return -1;
    }

    PyArg_ParseTuple(args,"i",&(self->idx));

    if( self->idx<0 || self->idx>dm::scada::CActionMgr::ins().size() ){
        log().warnning(STATICMODULE "索引(%d)溢出[0,%d]",self->idx,dm::scada::CActionMgr::ins().size());
        return -1;
    }

    self->pInfo = dm::scada::CActionMgr::ins().info(self->idx);

    return 0;
}

static PyObject* l_id( LObject* self ){
    return PyInt_FromLong(self->pInfo->id);
}

static PyObject* l_name( LObject* self ){
    return PyString_FromString(self->pInfo->name.c_str());
}

static PyObject* l_desc( LObject* self ){
    return PyString_FromString(self->pInfo->desc.c_str());
}

static PyObject* l_invOff( LObject* self ){
    return PyInt_FromLong(self->pInfo->desc_invOff);
}

static PyObject* l_off( LObject* self ){
    return PyInt_FromLong(self->pInfo->desc_off);
}

static PyObject* l_on( LObject* self ){
    return PyInt_FromLong(self->pInfo->desc_on);
}

static PyObject* l_invOn( LObject* self ){
    return PyInt_FromLong(self->pInfo->desc_invOn);
}

static PyObject* l_level( LObject* self ){
    return PyInt_FromLong(self->pInfo->level);
}

static PyObject* l_flagSave( LObject* self ){
    return PyInt_FromLong(self->pInfo->isFlagSave());
}

static PyObject* l_flagReport( LObject* self ){
    return PyInt_FromLong(self->pInfo->isFlagReportTimed());
}

static PyTypeObject lTypeObject = {
    PyVarObject_HEAD_INIT(NULL,0)
};

PyTypeObject* TypeAction = &lTypeObject;

static PyMethodDef lMethodDef[] = {
    {"id",(PyCFunction)l_id,METH_NOARGS,"获取动作ID"},

    {"name",(PyCFunction)l_name,METH_NOARGS,"获取动作名称"},
    {"desc",(PyCFunction)l_desc,METH_NOARGS,"获取动作描述"},
    {"invOff",(PyCFunction)l_invOff,METH_NOARGS,"获取无效分描述索引号"},
    {"off",(PyCFunction)l_off,METH_NOARGS,"获取分描述索引号"},
    {"on",(PyCFunction)l_on,METH_NOARGS,"获取合描述索引号"},
    {"invOn",(PyCFunction)l_invOn,METH_NOARGS,"获取无效合描述索引号"},
    {"level",(PyCFunction)l_level,METH_NOARGS,"获取级别"},
    {"flagSave",(PyCFunction)l_flagSave,METH_NOARGS,"获取标志:是否存盘"},
    {"flagReport",(PyCFunction)l_flagReport,METH_NOARGS,"获取标志:是否上报"},

    {NULL}
};

int init_action( PyObject* module ){
	lTypeObject.tp_dealloc = (destructor)l_dealloc;
    lTypeObject.tp_new = l_new;
	lTypeObject.tp_init = (initproc)l_init;
    lTypeObject.tp_repr = (reprfunc)l_repr;
	lTypeObject.tp_name = "Action";
	lTypeObject.tp_doc = "动作信息类";
	lTypeObject.tp_basicsize = sizeof(LObject);

	lTypeObject.tp_itemsize = 0;
	lTypeObject.tp_flags = Py_TPFLAGS_DEFAULT;
	lTypeObject.tp_methods = lMethodDef;

	if( PyType_Ready(&lTypeObject)<0 )
		return 0;

	Py_INCREF(&lTypeObject);
	PyModule_AddObject(module,"Action",(PyObject*)&lTypeObject);
	return 1;
}

}
}

这里的模版实现时,类型和对象都使用了别名,LObject, l_dealloc,等。方便类的模板套用,而不用改那么多的类型名和函数名。

关于PyObject的返回的处理的考量,参数错误的时候,我做的是使用return NULL。对于正常查询失败的返回None对象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章