使用C/C++写Python模块


最近看开源项目时学习了一下用C/C++写python模块,顺便把学习进行一下总结,废话少说直接开始:

环境:Windows、python2.78、VS2010或MingW

1 创建VC工程

(1) 打开VC6.0或VS2008,然后File-->New-->Project-->Win32 DLL Project。建立一个Empty Project,比如testClass,一路确定。

(2) 之后向工程添加python头文件目录及库文件目录,如头文件目录:F:\python278\include,库文件目录:F:\python278\libs

(3) 添加一个C++或C源文件,如工程中有用到类,则添加的必须是C++文件,这里直接添加main.cpp

 
#include <Python.h>
#include <iostream>
#include <sstream>
#include <structmember.h>
#include <windows.h>

using namespace std;  

typedef struct _CScore
{
    PyObject_HEAD
    char *m_szName;
    float m_dMath;
    float m_dEnglish;
}CScore;

static PyMemberDef CScore_DataMembers[] = {    //类/结构的数据成员的说明.
    {"m_szName",   T_STRING, offsetof(CScore, m_szName),   0, "The Name of instance"},
    {"m_dMath",    T_FLOAT,  offsetof(CScore, m_dMath),    0, "The Math score of instance."},
    {"m_dEnglish", T_FLOAT,  offsetof(CScore, m_dEnglish), 0, "The English score of instance."},
    {NULL, NULL, NULL, 0, NULL}
};

//////////////////////////////////////////////////////////////
// CScore类的所有内置、构造方法.
//
static void CScore_init(CScore* Self, PyObject* pArgs)        //构造方法.
{
    const char* Name = 0;
    if(!PyArg_ParseTuple(pArgs, "sff", &Name, &Self->m_dMath, &Self->m_dEnglish))
    {
        cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
        return ;
    }

    Self->m_szName = new char[strlen(Name) + 1];
    strcpy(Self->m_szName, Name);
}

static void CScore_Destruct(CScore* Self)                   //析构方法.
{
    if(Self->m_szName){
        delete [] Self->m_szName;                            //先释放其字符指针对象.
    }
    OutputDebugString(TEXT("destroy!!!"));

    //如果还有PyObject*成员的话,要一并释放之.
    //如:Py_XDECREF(Self->Member);
    Py_TYPE(Self)->tp_free((PyObject*)Self);                //释放对象/实例.
}

static PyObject* CScore_Str(CScore* Self)                    //调用str/print时自动调用此函数.
{
    ostringstream OStr;
    OStr<<"Name    : "<<Self->m_szName<<endl
        <<"Math    : "<<Self->m_dMath<<endl
        <<"English : "<<Self->m_dEnglish<<endl;
    string Str = OStr.str();
    return Py_BuildValue("s", Str.c_str());
}

static PyObject* CScore_Repr(CScore* Self)            //调用repr内置函数时自动调用.
{
    return CScore_Str(Self);
}


////////////////////////////////////////////////////////////
// CScore类的所有Get方法.
//
static PyObject* CScore_GetName(CScore* Self)
{
    return Py_BuildValue("s", Self->m_szName);
}

static PyObject* CScore_GetMath(CScore* Self)
{
    return Py_BuildValue("f", Self->m_dMath);
}

static PyObject* CScore_GetEnglish(CScore* Self)
{
    return Py_BuildValue("f", Self->m_dEnglish);
}

////////////////////////////////////////////////////////////
// CScore类的所有Set方法.
//
static PyObject* CScore_SetMath(CScore* Self, PyObject* Argvs)
{
    Py_INCREF(Py_None);
    if(!PyArg_ParseTuple(Argvs, "f", &Self->m_dMath))
    {
        cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
        return Py_None;
    }

    return Py_None;
}

static PyObject* CScore_SetEnglish(CScore* Self, PyObject* Argvs)
{
    Py_INCREF(Py_None);
    if(!PyArg_ParseTuple(Argvs, "f", &Self->m_dEnglish))
    {
        cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
        return Py_None;
    }

    return Py_None;
}

static PyObject* CScore_PrintInfo(CScore* Self)
{
    cout<<"The scores as follows:"<<endl
        <<"=============================="<<endl
        <<"Name    : "<<Self->m_szName<<endl
        <<"Math    : "<<Self->m_dMath<<endl
        <<"English : "<<Self->m_dEnglish<<endl
        <<"=============================="<<endl;

    Py_XINCREF(Py_None);
    return Py_None;
}

static PyMethodDef CScore_MethodMembers[] =      //类的所有成员函数结构列表.
{
    {"GetName",    (PyCFunction)CScore_GetName, METH_NOARGS,     "Get the name of instance."},
    {"GetMath",    (PyCFunction)CScore_GetMath, METH_NOARGS,     "Get the math score of instance."},
    {"GetEnglish", (PyCFunction)CScore_GetEnglish, METH_NOARGS,  "Get the english score of isntance."},

    {"SetMath",    (PyCFunction)CScore_SetMath, METH_VARARGS,    "Set the math score of instance."},
    {"SetEnglish", (PyCFunction)CScore_SetEnglish, METH_VARARGS, "Set the english of instance."},

    {"PrintInfo",  (PyCFunction)CScore_PrintInfo, METH_NOARGS,   "Print all information of instance."},

    {NULL, NULL, NULL, NULL}
};

////////////////////////////////////////////////////////////
// 类/结构的所有成员、内置属性的说明信息.
//
static PyTypeObject CScore_ClassInfo =
{
    PyVarObject_HEAD_INIT(NULL, 0)
    "Module.MyCppClass",            //可以通过__class__获得这个字符串. CPP可以用类.__name__获取.
    sizeof(CScore),                 //类/结构的长度.调用PyObject_New时需要知道其大小.
    0,
    (destructor)CScore_Destruct,    //类的析构函数.
    0,
    0,
    0,
    0,
    (reprfunc)CScore_Repr,          //repr 内置函数调用。
    0,
    0,
    0,
    0,
    0,
    (reprfunc)CScore_Str,          //Str/print内置函数调用.
    0,
    0,
    0,
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,                 //如果没有提供方法的话,为Py_TPFLAGS_DEFAULE
    "MyCppClass Objects---Extensioned by C++!",                   //__doc__,类/结构的DocString.
    0,
    0,
    0,
    0,
    0,
    0,
    CScore_MethodMembers,        //类的所有方法集合.
    CScore_DataMembers,          //类的所有数据成员集合.
    0,
    0,
    0,
    0,
    0,
    0,
    (initproc)CScore_init,      //类的构造函数.
    0,
};

////////////////////////////////////////////////////////////
// 此模块的说明信息. 由于我用的python2所以直接把该部分进行注释
//
/*static PyModuleDef ModuleInfo =
{
    PyModuleDef_HEAD_INIT,
    "My C++ Class Module",               //模块的内置名--__name__.
    "This Module Created By C++--extension a class to Python!",                 //模块的DocString.__doc__
    -1,
    NULL, NULL, NULL, NULL, NULL
};*/

int add(int x, int y)
{
    return x+y;
}

static PyObject* W_add(PyObject* self, PyObject* args) {
    int x;
    int y;
    if(!PyArg_ParseTuple(args, "i|i", &x, &y)) {
        return NULL;
    } else {
        return Py_BuildValue("i", add(x, y));
    }
}

static PyMethodDef module_methods[] = {{"add", W_add, METH_VARARGS, "a function from C"},{NULL, NULL, 0, NULL}};

PyMODINIT_FUNC inittestClass(void)       //模块外部名称为--CppClass
{
    PyObject* pReturn = 0;
    CScore_ClassInfo.tp_new = PyType_GenericNew;       //此类的new内置函数—建立对象.

    /////////////////////////////////////////////////////
    // 完成对象类型的初始化—包括添加其继承特性等等。
    // 如果成功,则返回0,否则返回-1并抛出异常.
    if(PyType_Ready(&CScore_ClassInfo) < 0)
        return;

    pReturn = Py_InitModule3("testClass", module_methods, "Example module that creates an extension type.");
    if(pReturn == NULL)
        return;
    Py_INCREF(&CScore_ClassInfo);
    PyModule_AddObject(pReturn, "CScore", (PyObject*)&CScore_ClassInfo); //将这个类加入到模块的Dictionary中.
    return;
}

之后修改VC工程导出文件后缀名为pyd

 

2 使用testClass模块

编译工程生成testClass.pyd模块文件,进入到导出文件目录,并启动python

导入testClass模块并查看其详细信息

模块详细使用

更多详情见请继续阅读下一页的精彩内容

  • 1
  • 2
  • 下一页

相关内容