使用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對象。

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