PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/branch/0.3.x/pykd_ext/pyclass.h

#
C Header | 207 lines | 175 code | 32 blank | 0 comment | 3 complexity | 2c46f937837cae5b0966bbc449dc809e MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Unlicense
  1. #pragma once
  2. #include "pyapi.h"
  3. #include <comutil.h>
  4. #include <string>
  5. #include <vector>
  6. struct convert_from_python
  7. {
  8. convert_from_python(PyObject* obj) : m_obj(obj){}
  9. operator std::wstring()
  10. {
  11. if (IsPy3())
  12. {
  13. std::vector<wchar_t> buf(0x10000);
  14. size_t len = buf.size();
  15. len = PyUnicode_AsWideChar(m_obj, &buf[0], len);
  16. return std::wstring(&buf[0], len);
  17. }
  18. else
  19. return std::wstring(_bstr_t(PyString_AsString(m_obj)));
  20. }
  21. operator std::string()
  22. {
  23. if (IsPy3())
  24. {
  25. std::vector<wchar_t> buf(0x10000);
  26. size_t len = buf.size();
  27. len = PyUnicode_AsWideChar(m_obj, &buf[0], len);
  28. std::wstring str(&buf[0], len);
  29. return std::string(_bstr_t(str.c_str()));
  30. }
  31. else
  32. return std::string(PyString_AsString(m_obj));
  33. }
  34. PyObject* m_obj;
  35. };
  36. struct convert_to_python
  37. {
  38. operator PyObject* (){
  39. return m_obj;
  40. }
  41. convert_to_python()
  42. {
  43. }
  44. convert_to_python(const std::wstring& str)
  45. {
  46. m_obj = PyUnicode_FromWideChar(str.c_str(), str.size());
  47. }
  48. convert_to_python(bool v)
  49. {
  50. m_obj = PyBool_FromLong(v == true ? 1 : 0);
  51. }
  52. PyObject* m_obj;
  53. };
  54. #define BEGIN_PYTHON_METHOD_MAP(classType, className) \
  55. template <typename TRet> \
  56. PyObject* callMethod0( \
  57. TRet (classType::*method)()) \
  58. { \
  59. TRet r = (this->*method)(); \
  60. return convert_to_python(r); \
  61. } \
  62. PyObject* callMethod0(\
  63. void (classType::*method)()) \
  64. { \
  65. (this->*method)(); \
  66. Py_IncRef(Py_None()); \
  67. return Py_None(); \
  68. } \
  69. template <typename TRet, typename V1> \
  70. PyObject* callMethod1( \
  71. TRet (classType::*method)(V1& v1), \
  72. convert_from_python& v1)\
  73. { \
  74. return (this->*method)(v1); \
  75. } \
  76. template <typename V1> \
  77. PyObject* callMethod1(\
  78. void(classType::*method)(V1& v1), \
  79. convert_from_python& v1)\
  80. { \
  81. (this->*method)(v1); \
  82. Py_IncRef(Py_None()); \
  83. return Py_None(); \
  84. } \
  85. template<typename T = classType> \
  86. static PyObject* getPythonClass() { \
  87. PyObject* args = PyTuple_New(3); \
  88. PyTuple_SetItem(args, 0, IsPy3() ? PyUnicode_FromString(className) : PyString_FromString(className)); \
  89. PyTuple_SetItem(args, 1, PyTuple_New(0)); \
  90. PyTuple_SetItem(args, 2, PyDict_New()); \
  91. PyObject* classTypeObj = PyObject_CallObject(PyType_Type(), args); \
  92. Py_DecRef(args);
  93. #define END_PYTHON_METHOD_MAP \
  94. return classTypeObj; \
  95. }
  96. #define PYTHON_METHOD0(name, fn, doc) \
  97. struct Call_##fn { \
  98. static PyObject* pycall(PyObject *s, PyObject *args) \
  99. { \
  100. PyObject* self = PyTuple_GetItem(args, 0); \
  101. PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
  102. T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
  103. Py_DecRef(cppobj); \
  104. return _this->callMethod0(&fn); \
  105. } \
  106. }; \
  107. {\
  108. static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
  109. PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
  110. PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
  111. PyObject_SetAttrString(classTypeObj, name, methodObj); \
  112. Py_DecRef(cFuncObj), Py_DecRef(methodObj); \
  113. }
  114. #define PYTHON_METHOD1(name, fn, doc) \
  115. struct Call_##fn { \
  116. static PyObject* pycall(PyObject *s, PyObject *args) \
  117. { \
  118. PyObject* self = PyTuple_GetItem(args, 0); \
  119. PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
  120. T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
  121. Py_DecRef(cppobj); \
  122. PyObject* v1 = PyTuple_GetItem(args, 1); \
  123. return _this->callMethod1(&fn, convert_from_python(v1)); \
  124. } \
  125. }; \
  126. {\
  127. static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
  128. PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
  129. PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
  130. PyObject_SetAttrString(classTypeObj, name, methodObj); \
  131. Py_DecRef(cFuncObj), Py_DecRef(methodObj); \
  132. }
  133. #define PYTHON_PROPERTY(name, fn, doc) \
  134. struct Call_##fn{ \
  135. static PyObject* pycall(PyObject *s, PyObject *args) \
  136. { \
  137. PyObject* self = PyTuple_GetItem(args, 0); \
  138. PyObject* cppobj = PyObject_GetAttrString(self, "cppobject"); \
  139. T* _this = reinterpret_cast<T*>(PyCapsule_GetPointer(cppobj, "cppobject")); \
  140. Py_DecRef(cppobj); \
  141. return _this->callMethod0(&fn); \
  142. } \
  143. }; \
  144. {\
  145. static PyMethodDef methodDef = { name, Call_##fn::pycall, METH_VARARGS }; \
  146. PyObject* cFuncObj = PyCFunction_NewEx(&methodDef, NULL, NULL); \
  147. PyObject* methodObj = IsPy3() ? PyInstanceMethod_New(cFuncObj) : PyMethod_New(cFuncObj, NULL, classTypeObj); \
  148. PyObject* args = PyTuple_New(4); \
  149. Py_IncRef(PyProperty_Type()); \
  150. PyTuple_SetItem(args, 0, methodObj); \
  151. PyTuple_SetItem(args, 1, Py_None()); \
  152. PyTuple_SetItem(args, 2, Py_None()); \
  153. PyTuple_SetItem(args, 3, IsPy3() ? PyUnicode_FromString(doc) : PyString_FromString(doc));\
  154. PyObject* propertyObj = PyObject_CallObject(PyProperty_Type(), args); \
  155. PyObject_SetAttrString(classTypeObj, name, propertyObj); \
  156. Py_DecRef(cFuncObj), Py_DecRef(propertyObj), Py_DecRef(args); \
  157. }
  158. template<typename T1>
  159. void delete_pyobject(PyObject* obj)
  160. {
  161. T1* cppobj = reinterpret_cast<T1*>(PyCapsule_GetPointer(obj, "cppobject"));
  162. delete cppobj;
  163. }
  164. template<typename T1, typename T2>
  165. PyObject* make_pyobject(const T2& var)
  166. {
  167. PyObject* cls = T1::getPythonClass();
  168. PyObject* p1 = PyObject_CallObject(cls, NULL);
  169. Py_DecRef(cls);
  170. T1* t1 = new T1(var);
  171. PyObject* p2 = PyCapsule_New(t1, "cppobject", delete_pyobject<T1>);
  172. PyObject_SetAttrString(p1, "cppobject", p2);
  173. Py_DecRef(p2);
  174. return p1;
  175. }