/branch/0.3.x/pykd_ext/pyclass.h
# · C Header · 207 lines · 175 code · 32 blank · 0 comment · 3 complexity · 2c46f937837cae5b0966bbc449dc809e MD5 · raw file
- #pragma once
-
- #include "pyapi.h"
-
-
- #include <comutil.h>
-
- #include <string>
- #include <vector>
-
- struct convert_from_python
- {
- convert_from_python(PyObject* obj) : m_obj(obj){}
-
- operator std::wstring()
- {
- if (IsPy3())
- {
- std::vector<wchar_t> buf(0x10000);
- size_t len = buf.size();
- len = PyUnicode_AsWideChar(m_obj, &buf[0], len);
- return std::wstring(&buf[0], len);
- }
- else
- return std::wstring(_bstr_t(PyString_AsString(m_obj)));
- }
-
- operator std::string()
- {
- if (IsPy3())
- {
- std::vector<wchar_t> buf(0x10000);
- size_t len = buf.size();
- len = PyUnicode_AsWideChar(m_obj, &buf[0], len);
- std::wstring str(&buf[0], len);
- return std::string(_bstr_t(str.c_str()));
- }
- else
- return std::string(PyString_AsString(m_obj));
- }
-
- PyObject* m_obj;
- };
-
- struct convert_to_python
- {
- operator PyObject* (){
- return m_obj;
- }
-
- convert_to_python()
- {
-
- }
-
- convert_to_python(const std::wstring& str)
- {
- m_obj = PyUnicode_FromWideChar(str.c_str(), str.size());
- }
-
- convert_to_python(bool v)
- {
- m_obj = PyBool_FromLong(v == true ? 1 : 0);
- }
-
- PyObject* m_obj;
- };
-
-
-
- #define BEGIN_PYTHON_METHOD_MAP(classType, className) \
- template <typename TRet> \
- PyObject* callMethod0( \
- TRet (classType::*method)()) \
- { \
- TRet r = (this->*method)(); \
- return convert_to_python(r); \
- } \
- PyObject* callMethod0(\
- void (classType::*method)()) \
- { \
- (this->*method)(); \
- Py_IncRef(Py_None()); \
- return Py_None(); \
- } \
- template <typename TRet, typename V1> \
- PyObject* callMethod1( \
- TRet (classType::*method)(V1& v1), \
- convert_from_python& v1)\
- { \
- return (this->*method)(v1); \
- } \
- template <typename V1> \
- PyObject* callMethod1(\
- void(classType::*method)(V1& v1), \
- convert_from_python& v1)\
- { \
- (this->*method)(v1); \
- Py_IncRef(Py_None()); \
- return Py_None(); \
- } \
- template<typename T = classType> \
- static PyObject* getPythonClass() { \
- PyObject* args = PyTuple_New(3); \
- PyTuple_SetItem(args, 0, IsPy3() ? PyUnicode_FromString(className) : PyString_FromString(className)); \
- PyTuple_SetItem(args, 1, PyTuple_New(0)); \
- PyTuple_SetItem(args, 2, PyDict_New()); \
- PyObject* classTypeObj = PyObject_CallObject(PyType_Type(), args); \
- Py_DecRef(args);
-
- #define END_PYTHON_METHOD_MAP \
- return classTypeObj; \
- }
-
- #define PYTHON_METHOD0(name, fn, doc) \
- struct Call_##fn { \
- static PyObject* pycall(PyObject *s, PyObject *args) \
- { \
- PyObject* self = PyTuple_GetItem(args, 0); \
- PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
- T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
- Py_DecRef(cppobj); \
- return _this->callMethod0(&fn); \
- } \
- }; \
- {\
- static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
- PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
- PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
- PyObject_SetAttrString(classTypeObj, name, methodObj); \
- Py_DecRef(cFuncObj), Py_DecRef(methodObj); \
- }
-
- #define PYTHON_METHOD1(name, fn, doc) \
- struct Call_##fn { \
- static PyObject* pycall(PyObject *s, PyObject *args) \
- { \
- PyObject* self = PyTuple_GetItem(args, 0); \
- PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
- T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
- Py_DecRef(cppobj); \
- PyObject* v1 = PyTuple_GetItem(args, 1); \
- return _this->callMethod1(&fn, convert_from_python(v1)); \
- } \
- }; \
- {\
- static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
- PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
- PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
- PyObject_SetAttrString(classTypeObj, name, methodObj); \
- Py_DecRef(cFuncObj), Py_DecRef(methodObj); \
- }
-
- #define PYTHON_PROPERTY(name, fn, doc) \
- struct Call_##fn{ \
- static PyObject* pycall(PyObject *s, PyObject *args) \
- { \
- PyObject* self = PyTuple_GetItem(args, 0); \
- PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
- T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
- Py_DecRef(cppobj); \
- return _this->callMethod0(&fn); \
- } \
- }; \
- {\
- static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
- PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
- PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
- PyObject* args = PyTuple_New(4); \
- Py_IncRef(PyProperty_Type()); \
- PyTuple_SetItem(args, 0, methodObj); \
- PyTuple_SetItem(args, 1, Py_None()); \
- PyTuple_SetItem(args, 2, Py_None()); \
- PyTuple_SetItem(args, 3, IsPy3() ? PyUnicode_FromString(doc) : PyString_FromString(doc));\
- PyObject* propertyObj = PyObject_CallObject(PyProperty_Type(), args); \
- PyObject_SetAttrString(classTypeObj, name, propertyObj); \
- Py_DecRef(cFuncObj), Py_DecRef(propertyObj), Py_DecRef(args); \
- }
-
-
-
- template<typename T1>
- void delete_pyobject(PyObject* obj)
- {
- T1* cppobj = reinterpret_cast<T1*>(PyCapsule_GetPointer(obj, "cppobject"));
- delete cppobj;
- }
-
- template<typename T1, typename T2>
- PyObject* make_pyobject(const T2& var)
- {
- PyObject* cls = T1::getPythonClass();
- PyObject* p1 = PyObject_CallObject(cls, NULL);
- Py_DecRef(cls);
-
- T1* t1 = new T1(var);
- PyObject* p2 = PyCapsule_New(t1, "cppobject", delete_pyobject<T1>);
-
- PyObject_SetAttrString(p1, "cppobject", p2);
-
- Py_DecRef(p2);
-
- return p1;
- }