python扩展:包装C++类

转载注明出处:http://blog.csdn.net/you_lan_hai/article/details/8597451

// TestPython.cpp : 定义控制台应用程序的入口点。
// author: 游蓝海
// blog: http://blog.csdn.net/you_lan_hai

#include "stdafx.h"

#include <iostream>
using namespace std;

#include "../python/Include/Python.h"
#include "../python/Include/structmember.h"

//有多个参数的python导出函数
static PyObject* py_test(PyObject* self, PyObject * args)
{
	cout<<"this message comes from C++"<<endl;

	Py_IncRef(Py_None);
	return Py_None;
}

//方法定义
static PyMethodDef lazyMethods[] =
{
	{"test", PyCFunction(py_test), METH_VARARGS, "just for test"},
	{NULL, NULL, NULL, NULL}, //结束标志
};

//python导出类
class TestPyClass : public PyObject
{
public:
	TestPyClass(PyTypeObject * pType)
		: id_(0)
		, score_(99)
	{
		if(PyType_Ready(pType) < 0)  
		{
			cout<<"PyType_Ready faild."<<endl;
		} 
		PyObject_INIT(this, pType);
	}
	virtual ~TestPyClass()
	{

	}

	static PyObject* py_new(PyTypeObject * pType, PyObject *, PyObject *)
	{
		return new TestPyClass(pType);
	}

	static void py_dealloc(PyObject * self)
	{
		delete (TestPyClass*)self;
	}

	//init方法。
	static int py_init(PyObject * self, PyObject * args, PyObject *)
	{
		TestPyClass* pThis = (TestPyClass*)self;
		if(!PyArg_ParseTuple(args, "ii", &pThis->id_, &pThis->score_))
		{
			return 0;
		}
		return 1;
	}

	PyObject* py_test(PyObject * args)
	{
		cout<<"this message comes from TestPyClass."<<endl;

		Py_IncRef(Py_None);
		return Py_None;
	}

	//导出函数
	static PyObject* _py_test(PyObject* self, PyObject * args)
	{
		return ((TestPyClass*)self)->py_test(args);
	}

	int id_;
	int score_;
};

/*如果类中有虚函数,则类对象开始地址为一个虚函数表的地址。
由于PyObject没有虚函数,而子类有虚函数,则子类与基类不共起始地址。
*/
#define offsetofVirtual(type, member) ( (int) & ((type*)0) -> member - sizeof(void*))

//成员变量
static PyMemberDef TestClassMembers[] =
{
	{"id", T_INT, offsetofVirtual(TestPyClass, id_), 0, "id"},
	{"score", T_INT, offsetofVirtual(TestPyClass, score_), 0, "score"},
	{NULL, NULL, NULL, 0, NULL},
};

//成员函数
static PyMethodDef TestClassMethods[] =
{
	{"test", PyCFunction(TestPyClass::_py_test), METH_VARARGS, "just for test"},
	{NULL, NULL, NULL, NULL},
};

//类类型
static PyTypeObject TestPyClass_Type = {
	PyVarObject_HEAD_INIT(&PyType_Type, 0)
	"TestPyClass",
	sizeof(TestPyClass),
	0,
	(destructor)TestPyClass::py_dealloc,		/* tp_dealloc */
	0,											/* tp_print */
	0,                                          /* tp_getattr */
	0,                                          /* tp_setattr */
	0,                                          /* tp_compare */
	0,											/* tp_repr */
	0,                                          /* tp_as_number */
	0,											/* tp_as_sequence */
	0,											/* tp_as_mapping */
	0,											/* tp_hash */
	0,                                          /* tp_call */
	0,                                          /* tp_str */
	0,											/* tp_getattro */
	0,                                          /* tp_setattro */
	0,                                          /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,	/* tp_flags */
	0,											/* tp_doc */
	0,											/* tp_traverse */
	0,											/* tp_clear */
	0,											/* tp_richcompare */
	0,                                          /* tp_weaklistoffset */
	0,											/* tp_iter */
	0,                                          /* tp_iternext */
	TestClassMethods,                           /* tp_methods */
	TestClassMembers,                           /* tp_members */
	0,                                          /* tp_getset */
	0,                                          /* tp_base */
	0,                                          /* tp_dict */
	0,                                          /* tp_descr_get */
	0,                                          /* tp_descr_set */
	0,                                          /* tp_dictoffset */
	(initproc)TestPyClass::py_init,             /* tp_init */
	0,											/* tp_alloc */
	(newfunc)TestPyClass::py_new,               /* tp_new */
	0,											/* tp_free */
};

void initLazy(void)
{
	PyObject* pModule = Py_InitModule("Lazy", lazyMethods);

	if (pModule)
	{
		Py_IncRef((PyObject*)&TestPyClass_Type);

		PyModule_AddObject(pModule, "TestClass", (PyObject*)&TestPyClass_Type);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	Py_SetPythonHome("F:/workspace/test/python");
	Py_Initialize();
	if (!Py_IsInitialized())
	{
		cout<<"Py_Initialize faild! "<<endl;
		PyErr_Print();
		return 0;
	}

	cout<<"Python initialize success."<<endl;
	initLazy();
	PyRun_SimpleString("import Lazy");
	PyRun_SimpleString("Lazy.test()");
	PyRun_SimpleString("a = Lazy.TestClass(2, 3)");
	PyRun_SimpleString("print dir(a)");
	PyRun_SimpleString("a.test()");
	PyRun_SimpleString("print 'a.id = ', a.id, ', a.score = ', a.score");

#if 0
	//测试对象大小。含虚函数的类,会大4个字节。
 	
	cout<<"sizeof(PyObject)"<<sizeof(PyObject)<<endl;
	cout<<"sizeof(TestPyClass)"<<sizeof(TestPyClass)<<endl;

	TestPyClass testPy(&TestPyClass_Type);
	cout<<"testPy addr:"<<&testPy<<" "<<(PyObject*)&testPy
		<<", id:"<<&(((TestPyClass*)0)->id_)<<endl;
#endif

	Py_Finalize();
	return 0;
}



posted @ 2017-10-19 18:07  游蓝海2017  阅读(854)  评论(0编辑  收藏  举报