1 //--------------------------------------------------------------------------
2 // Name:        wxpy_api.h
3 // Purpose:     Some utility functions and such that can be used in other
4 //              snippets of C++ code to help reduce complexity, etc.  They
5 //              are all either macros, inline functions, or functions that
6 //              are exported from the core extension module.
7 //
8 // Author:      Robin Dunn
9 //
10 // Created:     19-Nov-2010
11 // Copyright:   (c) 2010-2018 by Total Control Software
12 // Licence:     wxWindows license
13 //--------------------------------------------------------------------------
14 
15 #ifndef _WXPY_API_H
16 #define _WXPY_API_H
17 
18 #if defined(__APPLE__)
19     // When it's possible that we're building universal binaries with both
20     // 32-bit and 64-bit architectures then these need to be undef'ed because
21     // otherwise the values set by configure could conflict with those set
22     // based on runtime flags in Python's headers.  We also do something
23     // similar in wx/platform.h so it's okay to undef them now because they
24     // will be defined again soon.
25     #undef SIZEOF_VOID_P
26     #undef SIZEOF_LONG
27     #undef SIZEOF_SIZE_T
28 #endif
29 
30 #if defined(__GNUC__)
31     // Turn off the warning about converting string literals to char*
32     // TODO: fix these the right way...
33     #pragma GCC diagnostic ignored "-Wwrite-strings"
34 #endif
35 
36 #ifdef _MSC_VER
37     #pragma warning(disable:4800)
38     #pragma warning(disable:4190)
39 #endif
40 
41 #include <wx/wx.h>
42 
43 //--------------------------------------------------------------------------
44 // The API items that can be inline functions or macros.
45 // These are made available simply by #including this header file.
46 //--------------------------------------------------------------------------
47 
48 typedef PyGILState_STATE wxPyBlock_t;
49 #define wxPyBlock_t_default PyGILState_UNLOCKED
50 
51 typedef unsigned char  byte;
52 typedef unsigned char* buffer;
53 typedef unsigned long  ulong;
54 
55 
56 // Convert a wxString to a Python string (actually a PyUnicode object).
57 // Assumes that the GIL has already been acquired.
wx2PyString(const wxString & str)58 inline PyObject* wx2PyString(const wxString& str) {
59     return PyUnicode_FromWideChar(str.wc_str(), str.length());
60 }
61 
62 
63 // Calls from Python to wxWidgets code should be wrapped in calls to these
64 // functions:
wxPyBeginAllowThreads()65 inline PyThreadState* wxPyBeginAllowThreads() {
66     PyThreadState* saved = PyEval_SaveThread();  // Like Py_BEGIN_ALLOW_THREADS;
67     return saved;
68 }
69 
wxPyEndAllowThreads(PyThreadState * saved)70 inline void wxPyEndAllowThreads(PyThreadState* saved) {
71     PyEval_RestoreThread(saved);   // Like Py_END_ALLOW_THREADS;
72 }
73 
74 
75 
76 
77 // A macro that will help to execute simple statments wrapped in
78 // StartBlock/EndBlockThreads calls
79 #define wxPyBLOCK_THREADS(stmt) \
80     { wxPyThreadBlocker _blocker; stmt; }
81 
82 // Raise any exception with a string value  (blocking threads)
83 #define wxPyErr_SetString(err, str) \
84     wxPyBLOCK_THREADS(PyErr_SetString(err, str))
85 
86 
87 // Raise NotImplemented exceptions
88 #define wxPyRaiseNotImplemented() \
89     wxPyBLOCK_THREADS( PyErr_SetNone(PyExc_NotImplementedError) )
90 
91 
92 #define wxPyRaiseNotImplementedMsg(msg) \
93     wxPyBLOCK_THREADS( PyErr_SetString(PyExc_NotImplementedError, msg) );
94 
95 
96 // A convenience macro for properly returning Py_None
97 //#define RETURN_NONE()    { Py_INCREF(Py_None); return Py_None; }
98 #define RETURN_NONE()    { wxPyBLOCK_THREADS(Py_INCREF(Py_None)); return Py_None; }
99 
100 
101 
102 
103 // Macros to work around some of the differences in the Python 3 API
104 #if PY_MAJOR_VERSION >= 3
105     #define wxPyInt_Check            PyLong_Check
106     #define wxPyInt_AsLong           PyLong_AsLong
107     #define wxPyInt_AS_LONG          PyLong_AS_LONG
108     #define wxPyInt_AsSize_t         PyLong_AsSize_t
109     #define wxPyInt_AsSsize_t        PyLong_AsSsize_t
110     #define wxPyInt_AsUnsignedLong   PyLong_AsUnsignedLong
111     #define wxPyInt_FromLong         PyLong_FromLong
112     #define wxPyInt_FromSize_t       PyLong_FromSize_t
113     #define wxPyInt_FromSsize_t      PyLong_FromSsize_t
114     #define wxPyInt_FromUnsignedLong PyLong_FromUnsignedLong
115     #define wxPyNumber_Int           PyNumber_Long
116 #else
117     #define wxPyInt_Check            PyInt_Check
118     #define wxPyInt_AsLong           PyInt_AsLong
119     #define wxPyInt_AS_LONG          PyInt_AS_LONG
120     #define wxPyInt_AsLong           PyInt_AsLong
121     #define wxPyInt_AsSize_t(x)      static_cast<size_t>(PyInt_AsUnsignedLongLongMask(x))
122     #define wxPyInt_AsSsize_t        PyInt_AsSsize_t
123     #define wxPyInt_AsUnsignedLong   PyInt_AsUnsignedLongMask
124     #define wxPyInt_FromLong         PyInt_FromLong
125     #define wxPyInt_FromSize_t       PyInt_FromSize_t
126     #define wxPyInt_FromSsize_t      PyInt_FromSsize_t
127     #define wxPyInt_FromUnsignedLong PyInt_FromSize_t
128     #define wxPyNumber_Int           PyNumber_Int
129 #endif
130 
131 inline
wxPyUnicode_AsWideChar(PyObject * unicode,wchar_t * w,Py_ssize_t size)132 Py_ssize_t wxPyUnicode_AsWideChar(PyObject* unicode, wchar_t* w, Py_ssize_t size)
133 {
134     // GIL should already be held
135 #if PY_MAJOR_VERSION >= 3
136     return PyUnicode_AsWideChar(unicode, w, size);
137 #else
138     return PyUnicode_AsWideChar((PyUnicodeObject*)unicode, w, size);
139 #endif
140 }
141 
142 
143 
144 //--------------------------------------------------------------------------
145 // These are the API items whose implementation can not or should not be
146 // inline functions or macros. The implementations will instead be accessed
147 // via a structure of function pointers that is exported from the wx._core
148 // extension module. See wxpy_api.sip for the implementations.
149 //--------------------------------------------------------------------------
150 
151 struct wxPyAPI {
152     wxString      (*p_Py2wxString)(PyObject* source);
153     PyObject*     (*p_wxPyConstructObject)(void* ptr, const wxString& className, bool setThisOwn);
154     wxPyBlock_t   (*p_wxPyBeginBlockThreads)();
155     void          (*p_wxPyEndBlockThreads)(wxPyBlock_t blocked);
156     bool          (*p_wxPyWrappedPtr_Check)(PyObject* obj);
157     bool          (*p_wxPyConvertWrappedPtr)(PyObject* obj, void **ptr, const wxString& className);
158     bool          (*p_wxPy2int_seq_helper)(PyObject* source, int* i1, int* i2);
159     bool          (*p_wxPy4int_seq_helper)(PyObject* source, int* i1, int* i2, int* i3, int* i4);
160     bool          (*p_wxPyWrappedPtr_TypeCheck)(PyObject* obj, const wxString& className);
161     wxVariant     (*p_wxVariant_in_helper)(PyObject* obj);
162     PyObject*     (*p_wxVariant_out_helper)(const wxVariant& value);
163     bool          (*p_wxPyCheckForApp)(bool raiseException);
164     PyObject*     (*p_wxPyMakeBuffer)(void* ptr, Py_ssize_t len, bool readOnly);
165     bool          (*p_wxPyNumberSequenceCheck)(PyObject* obj, int reqLength);
166     void*         (*p_wxPyGetCppPtr)(sipSimpleWrapper* sipPyObj);
167     PyObject*     (*p_wxPyMethod_Self)(PyObject* method);
168     void          (*p_wxPyReinitializeModules)();
169 
170     int           (*p_wxPyDateTime_Check)(PyObject *obj);
171     int           (*p_wxPyDate_Check)(PyObject *obj);
172     wxDateTime*   (*p_wxPyDateTime_ToWxDateTime)(PyObject *obj);
173     wxDateTime*   (*p_wxPyDate_ToWxDateTime)(PyObject *obj);
174     // Always add new items here at the end.
175 };
176 
177 
178 
wxPyGetAPIPtr()179 inline wxPyAPI* wxPyGetAPIPtr()
180 {
181     static wxPyAPI* wxPyAPIPtr = NULL;
182 
183     if (wxPyAPIPtr == NULL) {
184         PyGILState_STATE state = PyGILState_Ensure();
185         wxPyAPIPtr = (wxPyAPI*)PyCapsule_Import("wx._wxPyAPI", 0);
186         // uncomment if needed for debugging
187         //if (PyErr_Occurred()) { PyErr_Print(); }
188         //wxASSERT_MSG(wxPyAPIPtr != NULL, wxT("wxPyAPIPtr is NULL!!!"));
189         PyGILState_Release(state);
190     }
191 
192     return wxPyAPIPtr;
193 }
194 
195 //--------------------------------------------------------------------------
196 // Inline wrappers which call the functions in the API structure
197 
198 // Convert a PyObject to a wxString
199 // Assumes that the GIL has already been acquired.
Py2wxString(PyObject * source)200 inline wxString Py2wxString(PyObject* source)
201     { return wxPyGetAPIPtr()->p_Py2wxString(source); }
202 
203 
204 // Create a PyObject of the requested type from a void* and a class name.
205 // Assumes that the GIL has already been acquired.
206 inline PyObject* wxPyConstructObject(void* ptr, const wxString& className, bool setThisOwn=false)
207     { return wxPyGetAPIPtr()->p_wxPyConstructObject(ptr, className, setThisOwn); }
208 
209 
210 // Check if a PyObject is a wrapped type
wxPyWrappedPtr_Check(PyObject * obj)211 inline bool wxPyWrappedPtr_Check(PyObject* obj)
212     { return wxPyGetAPIPtr()->p_wxPyWrappedPtr_Check(obj); }
213 
214 // Check if a PyObject is a specific wrapped type (or a subclass)
wxPyWrappedPtr_TypeCheck(PyObject * obj,const wxString & className)215 inline bool wxPyWrappedPtr_TypeCheck(PyObject* obj, const wxString& className)
216     { return wxPyGetAPIPtr()->p_wxPyWrappedPtr_TypeCheck(obj, className); }
217 
218 
219 // Convert a wrapped SIP object to its C++ pointer, ensuring that it is of the expected type
wxPyConvertWrappedPtr(PyObject * obj,void ** ptr,const wxString & className)220 inline bool wxPyConvertWrappedPtr(PyObject* obj, void **ptr, const wxString& className)
221     { return wxPyGetAPIPtr()->p_wxPyConvertWrappedPtr(obj, ptr, className); }
222 
223 
224 // Calls from wxWindows back to Python code, or even any PyObject
225 // manipulations, PyDECREF's and etc. should be wrapped in calls to these functions:
wxPyBeginBlockThreads()226 inline wxPyBlock_t wxPyBeginBlockThreads()
227     { return wxPyGetAPIPtr()->p_wxPyBeginBlockThreads(); }
228 
wxPyEndBlockThreads(wxPyBlock_t blocked)229 inline void wxPyEndBlockThreads(wxPyBlock_t blocked)
230     { wxPyGetAPIPtr()->p_wxPyEndBlockThreads(blocked); }
231 
232 
233 
234 // A helper for converting a 2 element sequence to a pair of integers
wxPy2int_seq_helper(PyObject * source,int * i1,int * i2)235 inline bool wxPy2int_seq_helper(PyObject* source, int* i1, int* i2)
236     { return wxPyGetAPIPtr()->p_wxPy2int_seq_helper(source, i1, i2); }
237 
238 // A helper for converting a 4 element sequence to a set of integers
wxPy4int_seq_helper(PyObject * source,int * i1,int * i2,int * i3,int * i4)239 inline bool wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4)
240     { return wxPyGetAPIPtr()->p_wxPy4int_seq_helper(source, i1, i2, i3, i4); }
241 
242 
243 // Convert a PyObject to a wxVariant
wxVariant_in_helper(PyObject * obj)244 inline wxVariant wxVariant_in_helper(PyObject* obj)
245     { return wxPyGetAPIPtr()->p_wxVariant_in_helper(obj); }
246 
247 // Convert a wxVariant to a PyObject
wxVariant_out_helper(const wxVariant & value)248 inline PyObject* wxVariant_out_helper(const wxVariant& value)
249     { return wxPyGetAPIPtr()->p_wxVariant_out_helper(value); }
250 
251 
252 // Check if a wx.App object has been created
253 inline bool wxPyCheckForApp(bool raiseException=true)
254     { return wxPyGetAPIPtr()->p_wxPyCheckForApp(raiseException); }
255 
256 
257 // Create a buffer object from a pointer and size
258 inline PyObject* wxPyMakeBuffer(void* ptr, Py_ssize_t len, bool readOnly=false)
259     { return wxPyGetAPIPtr()->p_wxPyMakeBuffer(ptr, len, readOnly); }
260 
261 // Check if an object is a sequence of numbers
262 inline bool wxPyNumberSequenceCheck(PyObject* obj, int reqLength=-1)
263     { return wxPyGetAPIPtr()->p_wxPyNumberSequenceCheck(obj, reqLength); }
264 
265 
wxPyGetCppPtr(sipSimpleWrapper * sipPyObj)266 inline void* wxPyGetCppPtr(sipSimpleWrapper* sipPyObj)
267     { return wxPyGetAPIPtr()->p_wxPyGetCppPtr(sipPyObj); }
268 
wxPyMethod_Self(PyObject * method)269 inline PyObject* wxPyMethod_Self(PyObject* method)
270     { return wxPyGetAPIPtr()->p_wxPyMethod_Self(method); }
271 
272 
wxPyReinitializeModules()273 inline void wxPyReinitializeModules()
274     { return wxPyGetAPIPtr()->p_wxPyReinitializeModules(); }
275 
276 
277 
wxPyDateTime_Check(PyObject * obj)278 inline int wxPyDateTime_Check(PyObject *obj)
279     { return wxPyGetAPIPtr()->p_wxPyDateTime_Check(obj); }
280 
wxPyDate_Check(PyObject * obj)281 inline int wxPyDate_Check(PyObject *obj)
282     { return wxPyGetAPIPtr()->p_wxPyDate_Check(obj); }
283 
wxPyDateTime_ToWxDateTime(PyObject * obj)284 inline wxDateTime* wxPyDateTime_ToWxDateTime(PyObject *obj)
285     { return wxPyGetAPIPtr()->p_wxPyDateTime_ToWxDateTime(obj); }
286 
wxPyDate_ToWxDateTime(PyObject * obj)287 inline wxDateTime* wxPyDate_ToWxDateTime(PyObject *obj)
288     { return wxPyGetAPIPtr()->p_wxPyDate_ToWxDateTime(obj); }
289 
290 
291 //--------------------------------------------------------------------------
292 // Convenience helper for RAII-style thread blocking
293 
294 class wxPyThreadBlocker {
295 public:
296     explicit wxPyThreadBlocker(bool block=true)
297         :   m_oldstate(block ?  wxPyBeginBlockThreads() : wxPyBlock_t_default),
298             m_block(block)
299     { }
300 
~wxPyThreadBlocker()301     ~wxPyThreadBlocker() {
302         if (m_block) {
303             wxPyEndBlockThreads(m_oldstate);
304         }
305     }
306 
307 private:
308     void operator=(const wxPyThreadBlocker&);
309     explicit wxPyThreadBlocker(const wxPyThreadBlocker&);
310     wxPyBlock_t m_oldstate;
311     bool        m_block;
312 };
313 
314 
315 //--------------------------------------------------------------------------
316 // helper template to make common code for all of the various user data owners
317 
318 template<typename Base>
319 class wxPyUserDataHelper : public Base {
320 public:
321     explicit wxPyUserDataHelper(PyObject* obj = NULL)
322         : m_obj(obj ? obj : Py_None)
323     {
324         wxPyThreadBlocker blocker;
325         Py_INCREF(m_obj);
326     }
327 
~wxPyUserDataHelper()328     ~wxPyUserDataHelper()
329     {   // normally the derived class does the clean up, or deliberately leaks
330         // by setting m_obj to 0, but if not then do it here.
331         if (m_obj) {
332             wxPyThreadBlocker blocker;
333             Py_DECREF(m_obj);
334             m_obj = 0;
335         }
336     }
337 
338     // Return Value: New reference
GetData()339     PyObject* GetData() const {
340         wxPyThreadBlocker blocker;
341         Py_INCREF(m_obj);
342         return m_obj;
343     }
344 
345     // Return Value: Borrowed reference
BorrowData()346     PyObject* BorrowData() const {
347         return m_obj;
348     }
349 
SetData(PyObject * obj)350     void SetData(PyObject* obj) {
351         if (obj != m_obj) {
352             wxPyThreadBlocker blocker;
353             Py_DECREF(m_obj);
354             m_obj = obj ? obj : Py_None;
355             Py_INCREF(m_obj);
356         }
357     }
358 
359     // Return the object in udata or None if udata is null
360     // Return Value: New reference
SafeGetData(wxPyUserDataHelper<Base> * udata)361     static PyObject* SafeGetData(wxPyUserDataHelper<Base>* udata) {
362         wxPyThreadBlocker blocker;
363         PyObject* obj = udata ? udata->BorrowData() : Py_None;
364         Py_INCREF(obj);
365         return obj;
366     }
367 
368     // Set the m_obj to null, this should only be used during clean up, when
369     // the object should be leaked.
370     // Calling any other methods on this object is then undefined behaviour
ReleaseDataDuringCleanup()371     void ReleaseDataDuringCleanup()
372     {
373         m_obj = 0;
374     }
375 
376 private:
377     PyObject* m_obj;
378 };
379 
380 
381 
382 // A wxClientData that holds a reference to a Python object
383 class wxPyClientData : public wxPyUserDataHelper<wxClientData>
384 {
385 public:
386     wxPyClientData(PyObject* obj = NULL)
387         : wxPyUserDataHelper<wxClientData>(obj)
388     { }
389 };
390 
391 
392 
393 
394 // A wxObject object that holds a reference to a Python object
395 class wxPyUserData : public wxPyUserDataHelper<wxObject>
396 {
397 public:
398     wxPyUserData(PyObject* obj = NULL)
399         : wxPyUserDataHelper<wxObject>(obj)
400     { }
401 };
402 
403 
404 //--------------------------------------------------------------------------
405 #endif
406