1/*
2 * Wrappers for methods with callback functions.
3 */
4#include "Python.h"
5#include "pyobjc-api.h"
6
7#import <Foundation/Foundation.h>
8
9static int
10SortHelperFunc(id arg1, id arg2, void* opaque)
11{
12	PyObjC_BEGIN_WITH_GIL
13
14		PyObject* func = PyTuple_GetItem((PyObject*)opaque, 0);
15		PyObject* context = PyTuple_GetItem((PyObject*)opaque, 1);
16		PyObject* a1;
17		PyObject* a2;
18		PyObject* r;
19		int res;
20
21		if (func == NULL || context == NULL) {
22			PyObjC_GIL_FORWARD_EXC();
23		}
24
25		a1 = PyObjC_IdToPython(arg1);
26		if (a1 == NULL) {
27			PyObjC_GIL_FORWARD_EXC();
28		}
29
30		a2 = PyObjC_IdToPython(arg2);
31		if (a2 == NULL) {
32			Py_DECREF(a1);
33			PyObjC_GIL_FORWARD_EXC();
34		}
35
36		r = PyObject_CallFunction(func, "OOO", a1, a2, context);
37		Py_DECREF(a1);
38		Py_DECREF(a2);
39		if (r == NULL) {
40			PyObjC_GIL_FORWARD_EXC();
41		}
42
43		if (PyObjC_PythonToObjC(@encode(int), r, &res) < 0) {
44			Py_DECREF(r);
45			PyObjC_GIL_FORWARD_EXC();
46		}
47		Py_DECREF(r);
48
49		PyObjC_GIL_RETURN(res);
50	PyObjC_END_WITH_GIL
51
52}
53
54static PyObject*
55call_NSArray_sortedArrayUsingFunction_context_(
56		PyObject* method, PyObject* self, PyObject* arguments)
57{
58	PyObject* result;
59	struct objc_super super;
60	PyObject* sortFunc;
61	PyObject* context;
62	PyObject* realContext;
63	id  res;
64
65	if  (!PyArg_ParseTuple(arguments, "OO", &sortFunc, &context)) {
66		return NULL;
67	}
68
69	realContext = PyTuple_New(2);
70	if (realContext == NULL) {
71		return NULL;
72	}
73	PyTuple_SET_ITEM(realContext, 0, sortFunc);
74	Py_INCREF(sortFunc);
75	PyTuple_SET_ITEM(realContext, 1, context);
76	Py_INCREF(context);
77
78	PyObjC_DURING
79		if (PyObjCIMP_Check(method)) {
80			res = ((id(*)(id,SEL, int(*)(id, id, void*), void*))
81				(PyObjCIMP_GetIMP(method)))(
82					PyObjCObject_GetObject(self),
83					PyObjCIMP_GetSelector(method),
84					SortHelperFunc, realContext);
85		} else {
86			PyObjC_InitSuper(&super,
87				PyObjCSelector_GetClass(method),
88				PyObjCObject_GetObject(self));
89
90
91			res = objc_msgSendSuper(&super,
92					PyObjCSelector_GetSelector(method),
93					SortHelperFunc, realContext);
94		}
95	PyObjC_HANDLER
96		PyObjCErr_FromObjC(localException);
97		res = nil;
98	PyObjC_ENDHANDLER
99
100	Py_DECREF(realContext);
101
102	if (res == nil && PyErr_Occurred()) {
103		return NULL;
104	}
105
106	result = PyObjC_IdToPython(res);
107
108	return result;
109}
110
111static PyObject*
112call_NSArray_sortedArrayUsingFunction_context_hint_(
113		PyObject* method, PyObject* self, PyObject* arguments)
114{
115	PyObject* result;
116	struct objc_super super;
117	PyObject* sortFunc;
118	PyObject* context;
119	id hint = nil;
120	PyObject* realContext;
121	id  res;
122
123	if  (!PyArg_ParseTuple(arguments, "OOO&", &sortFunc, &context,
124			PyObjCObject_Convert, &hint)) {
125		return NULL;
126	}
127
128	realContext = PyTuple_New(2);
129	if (realContext == NULL) {
130		return NULL;
131	}
132	PyTuple_SET_ITEM(realContext, 0, sortFunc);
133	Py_INCREF(sortFunc);
134	PyTuple_SET_ITEM(realContext, 1, context);
135	Py_INCREF(context);
136
137	PyObjC_DURING
138		if (PyObjCIMP_Check(method)) {
139			res = ((id(*)(id,SEL, int(*)(id, id, void*), void*, id))
140				(PyObjCIMP_GetIMP(method)))(
141					PyObjCObject_GetObject(self),
142					PyObjCIMP_GetSelector(method),
143					SortHelperFunc, realContext, hint);
144		} else {
145			PyObjC_InitSuper(&super,
146				PyObjCSelector_GetClass(method),
147				PyObjCObject_GetObject(self));
148
149			res = objc_msgSendSuper(&super,
150				 PyObjCSelector_GetSelector(method),
151				 SortHelperFunc, realContext, hint);
152		}
153	PyObjC_HANDLER
154		PyObjCErr_FromObjC(localException);
155		res = nil;
156	PyObjC_ENDHANDLER
157
158	Py_DECREF(realContext);
159
160	if (res == nil && PyErr_Occurred()) {
161		return NULL;
162	}
163
164	result = PyObjC_IdToPython(res);
165
166	return result;
167}
168
169
170static PyObject*
171call_NSMutableArray_sortUsingFunction_context_(
172	PyObject* method, PyObject* self, PyObject* arguments)
173{
174	PyObject* result;
175	struct objc_super super;
176	PyObject* sortFunc;
177	PyObject* context;
178	PyObject* realContext;
179	id  res;
180
181	if  (!PyArg_ParseTuple(arguments, "OO", &sortFunc, &context)) {
182		return NULL;
183	}
184
185	realContext = PyTuple_New(2);
186	if (realContext == NULL) {
187		return NULL;
188	}
189	PyTuple_SET_ITEM(realContext, 0, sortFunc);
190	Py_INCREF(sortFunc);
191	PyTuple_SET_ITEM(realContext, 1, context);
192	Py_INCREF(context);
193
194	PyObjC_DURING
195		PyObjC_InitSuper(&super,
196			PyObjCSelector_GetClass(method),
197			PyObjCObject_GetObject(self));
198
199
200		(void)objc_msgSendSuper(&super,
201				@selector(sortUsingFunction:context:),
202				 SortHelperFunc, realContext);
203		res = nil;
204	PyObjC_HANDLER
205		PyObjCErr_FromObjC(localException);
206		res = nil;
207	PyObjC_ENDHANDLER
208
209	Py_DECREF(realContext);
210
211	if (res == nil && PyErr_Occurred()) {
212		return NULL;
213	}
214
215	result = PyObjC_IdToPython(res);
216
217	return result;
218}
219
220static PyObject*
221call_NSMutableArray_sortUsingFunction_context_range_(
222	PyObject* method, PyObject* self, PyObject* arguments)
223{
224	PyObject* result;
225	struct objc_super super;
226	PyObject* sortFunc;
227	PyObject* context;
228	PyObject* rangeObj;
229	NSRange range;
230	PyObject* realContext;
231	id  res;
232
233	if  (!PyArg_ParseTuple(arguments, "OOO", &sortFunc, &context,
234			 &rangeObj)) {
235		return NULL;
236	}
237
238	if (PyObjC_PythonToObjC(@encode(NSRange), rangeObj, &range) < 0) {
239		return NULL;
240	}
241
242	realContext = PyTuple_New(2);
243	if (realContext == NULL) {
244		return NULL;
245	}
246	PyTuple_SET_ITEM(realContext, 0, sortFunc);
247	Py_INCREF(sortFunc);
248	PyTuple_SET_ITEM(realContext, 1, context);
249	Py_INCREF(context);
250
251	PyObjC_DURING
252		PyObjC_InitSuper(&super,
253			PyObjCSelector_GetClass(method),
254			PyObjCObject_GetObject(self));
255
256
257		(void)objc_msgSendSuper(&super,
258			@selector(sortUsingFunction:context:range:),
259			 SortHelperFunc, realContext, range);
260		res = nil;
261	PyObjC_HANDLER
262		PyObjCErr_FromObjC(localException);
263		res = nil;
264	PyObjC_ENDHANDLER
265
266	Py_DECREF(realContext);
267
268	if (res == nil && PyErr_Occurred()) {
269		return NULL;
270	}
271
272	result = PyObjC_IdToPython(res);
273
274	return result;
275}
276
277PyDoc_STRVAR(mod_doc, "");
278
279static PyMethodDef mod_methods[] = {
280        { 0, 0, 0, 0 } /* sentinel */
281};
282
283
284
285void init_functioncallbacks(void);
286
287void
288init_functioncallbacks(void)
289{
290	PyObject* m = Py_InitModule4("_functioncallbacks", mod_methods,
291		mod_doc, NULL, PYTHON_API_VERSION);
292
293	if (PyObjC_ImportAPI(m) < 0) { return; }
294
295	Class classNSArray = objc_lookUpClass("NSArray");
296
297	/* XXX: this one is mostly here because I'd like to add support someday
298	 */
299	if (PyObjC_RegisterMethodMapping(
300		classNSArray,
301		@selector(apply:context:),
302		PyObjCUnsupportedMethod_Caller,
303		PyObjCUnsupportedMethod_IMP) < 0) {
304
305		return;
306	}
307
308	if (PyObjC_RegisterMethodMapping(
309		classNSArray,
310		@selector(sortedArrayUsingFunction:context:),
311		call_NSArray_sortedArrayUsingFunction_context_,
312		PyObjCUnsupportedMethod_IMP) < 0) {
313
314		return;
315	}
316
317	if (PyObjC_RegisterMethodMapping(
318		classNSArray,
319		@selector(sortedArrayUsingFunction:context:hint:),
320		call_NSArray_sortedArrayUsingFunction_context_hint_,
321		PyObjCUnsupportedMethod_IMP) < 0) {
322
323		return;
324	}
325
326
327
328	Class classNSMutableArray = objc_lookUpClass("NSMutableArray");
329
330	if (PyObjC_RegisterMethodMapping(
331		classNSMutableArray,
332		@selector(sortUsingFunction:context:),
333		call_NSMutableArray_sortUsingFunction_context_,
334		PyObjCUnsupportedMethod_IMP) < 0) {
335
336		return;
337	}
338
339	if (PyObjC_RegisterMethodMapping(
340		classNSMutableArray,
341		@selector(sortUsingFunction:context:range:),
342		call_NSMutableArray_sortUsingFunction_context_range_,
343		PyObjCUnsupportedMethod_IMP) < 0) {
344
345		return;
346	}
347}
348