最近看開源項目時學習了一下用C/C++寫python模塊,順便把學習進行一下總結,廢話少說直接開始:
環境:Windows、python2.78、VS2010或MingW
(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;
}
main.cpp
之後修改VC工程導出文件後綴名為pyd
編譯工程生成testClass.pyd模塊文件,進入到導出文件目錄,並啟動python
導入testClass模塊並查看其詳細信息
模塊詳細使用
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-07/133126p2.htm