1 // This is the support code for QMetaObject.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of PyQt5.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file. Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license. For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
20
21 #include <Python.h>
22
23 #include <QGenericArgument>
24 #include <QGenericReturnArgument>
25
26 #include "qpycore_api.h"
27 #include "qpycore_chimera.h"
28 #include "qpycore_misc.h"
29
30 #include "sipAPIQtCore.h"
31
32
33 // Forward declarations.
34 static PyObject *ArgumentStorage_New(PyObject *type, PyObject *data);
35 #if defined(SIP_USE_PYCAPSULE)
36 extern "C" {static void ArgumentStorage_delete(PyObject *cap);}
37 #else
38 extern "C" {static void ArgumentStorage_delete(void *stv);}
39 #endif
40
41
42 // Return a wrapped QGenericArgument for the given type and Python object.
qpycore_ArgumentFactory(PyObject * type,PyObject * data)43 PyObject *qpycore_ArgumentFactory(PyObject *type, PyObject *data)
44 {
45 PyObject *as_obj = ArgumentStorage_New(type, data);
46
47 if (!as_obj)
48 {
49 Chimera::raiseParseException(type, "a Q_ARG()");
50 return 0;
51 }
52
53 #if defined(SIP_USE_PYCAPSULE)
54 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
55 PyCapsule_GetPointer(as_obj, NULL));
56 #else
57 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
58 PyCObject_AsVoidPtr(as_obj));
59 #endif
60
61 QGenericArgument *arg = new QGenericArgument(
62 st->type()->name().constData(), st->address());
63
64 PyObject *ga_obj = sipConvertFromNewType(arg, sipType_QGenericArgument, 0);
65
66 if (ga_obj)
67 {
68 // Stash the storage in the user field so that everything will be
69 // properly garbage collected.
70 sipSetUserObject((sipSimpleWrapper *)ga_obj, as_obj);
71 }
72 else
73 {
74 delete arg;
75 Py_DECREF(as_obj);
76 }
77
78 return ga_obj;
79 }
80
81
82 // Return a wrapped QGenericReturnArgument for the given type.
qpycore_ReturnFactory(PyObject * type)83 PyObject *qpycore_ReturnFactory(PyObject *type)
84 {
85 PyObject *as_obj = ArgumentStorage_New(type, 0);
86
87 if (!as_obj)
88 {
89 Chimera::raiseParseException(type, "a Q_RETURN_ARG()");
90 return 0;
91 }
92
93 #if defined(SIP_USE_PYCAPSULE)
94 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
95 PyCapsule_GetPointer(as_obj, NULL));
96 #else
97 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
98 PyCObject_AsVoidPtr(as_obj));
99 #endif
100
101 QGenericReturnArgument *arg = new QGenericReturnArgument(
102 st->type()->name().constData(), st->address());
103
104 PyObject *gra_obj = sipConvertFromNewType(arg,
105 sipType_QGenericReturnArgument, 0);
106
107 if (gra_obj)
108 {
109 // Stash the storage in the user field so that everything will be
110 // properly garbage collected.
111 sipSetUserObject((sipSimpleWrapper *)gra_obj, as_obj);
112 }
113 else
114 {
115 delete arg;
116 Py_DECREF(as_obj);
117 }
118
119 return gra_obj;
120 }
121
122
123 // Return the Python result from a QGenericReturnArgument.
qpycore_ReturnValue(PyObject * gra_obj)124 PyObject *qpycore_ReturnValue(PyObject *gra_obj)
125 {
126 PyObject *as_obj = sipGetUserObject((sipSimpleWrapper *)gra_obj);
127
128 #if defined(SIP_USE_PYCAPSULE)
129 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
130 PyCapsule_GetPointer(as_obj, NULL));
131 #else
132 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
133 PyCObject_AsVoidPtr(as_obj));
134 #endif
135
136 return st->toPyObject();
137 }
138
139
140 #if defined(SIP_USE_PYCAPSULE)
141 // The PyCapsule destructor for the ArgumentStorage type.
ArgumentStorage_delete(PyObject * cap)142 static void ArgumentStorage_delete(PyObject *cap)
143 {
144 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(
145 PyCapsule_GetPointer(cap, NULL));
146 const Chimera *ct = st->type();
147
148 delete st;
149 delete ct;
150 }
151 #else
152 // The PyCObject destructor for the ArgumentStorage type.
ArgumentStorage_delete(void * stv)153 static void ArgumentStorage_delete(void *stv)
154 {
155 Chimera::Storage *st = reinterpret_cast<Chimera::Storage *>(stv);
156 const Chimera *ct = st->type();
157
158 delete st;
159 delete ct;
160 }
161 #endif
162
163
164 // Returns a Python object wrapping an ArgumentStorage instance.
ArgumentStorage_New(PyObject * type,PyObject * data)165 static PyObject *ArgumentStorage_New(PyObject *type, PyObject *data)
166 {
167 const Chimera *ct = Chimera::parse(type);
168
169 if (!ct)
170 return 0;
171
172 Chimera::Storage *st;
173
174 if (data)
175 st = ct->fromPyObjectToStorage(data);
176 else
177 st = ct->storageFactory();
178
179 if (!st)
180 {
181 delete ct;
182 return 0;
183 }
184
185 // Convert to a Python object.
186 #if defined(SIP_USE_PYCAPSULE)
187 PyObject *as_obj = PyCapsule_New(st, NULL, ArgumentStorage_delete);
188 #else
189 PyObject *as_obj = PyCObject_FromVoidPtr(st, ArgumentStorage_delete);
190 #endif
191
192 if (!as_obj)
193 {
194 delete st;
195 delete ct;
196 }
197
198 return as_obj;
199 }
200