1/*
2 * This file defines the glue code that is needed to access the objc module
3 * from other modules.
4 *
5 * Why would you want to do that?
6 * - To wrap native functions that use Objective-C objects as arguments or
7 *   return values
8 * - To add custom wrappers for troublesome methods in specific classes
9 * - To generic support for additional method signatures
10 */
11#include "pyobjc.h"
12
13#ifdef PyObjCObject_GetObject
14#undef PyObjCObject_GetObject
15#endif
16
17static void do_weaklink(PyObject* module_dict, struct PyObjC_WeakLink* funcs)
18{
19	while (funcs->name) {
20		if (!funcs->func) {
21			if (PyDict_DelItemString(
22					module_dict,
23					funcs->name) == -1) {
24				PyErr_Clear();
25			}
26		}
27		funcs++;
28	}
29}
30
31static int obj_is_uninitialized(PyObject* object)
32{
33	if (!PyObjCObject_Check(object)) {
34		return -1;
35	}
36	return (PyObjCObject_GetFlags(object) & PyObjCObject_kUNINITIALIZED) != 0;
37}
38
39static id python_to_id(PyObject* object)
40{
41	id result;
42	int err;
43
44	err = depythonify_c_value(@encode(id), object, &result);
45	if (err == -1) {
46		return nil;
47	}
48
49	return result;
50}
51
52static PyObject* id_to_python(id object)
53{
54	PyObject* result;
55
56	result = pythonify_c_value(@encode(id), &object);
57	return result;
58}
59
60static Class      sel_get_class(PyObject* sel)
61{
62	if (!PyObjCNativeSelector_Check(sel)) {
63		PyErr_SetString(PyExc_TypeError, "Expecting PyObjCSelector");
64		return NULL;
65	}
66	return ((PyObjCNativeSelector*)sel)->sel_class;
67}
68
69static SEL      sel_get_sel(PyObject* sel)
70{
71	if (!PyObjCSelector_Check(sel)) {
72		PyErr_SetString(PyExc_TypeError, "Expecting PyObjCSelector");
73		return NULL;
74	}
75	return ((PyObjCSelector*)sel)->sel_selector;
76}
77
78static void 	fill_super(struct objc_super* super, Class cls, id receiver)
79{
80	objc_superSetReceiver(*super, receiver);
81	objc_superSetClass(*super, cls);
82}
83
84static void 	fill_super_cls(struct objc_super* super, Class cls, Class self)
85{
86	objc_superSetReceiver(*super, self);
87	objc_superSetClass(*super, object_getClass(cls));
88}
89
90static int depythonify_c_array_count2(const char* type, Py_ssize_t count, BOOL strict, PyObject* value, void* datum)
91{
92	return depythonify_c_array_count(type, count, strict, value, datum, NO, NO);
93}
94
95
96
97
98struct pyobjc_api objc_api = {
99	PYOBJC_API_VERSION,		/* api_version */
100	sizeof(struct pyobjc_api),	/* struct_size */
101	&PyObjCClass_Type,		/* class_type */
102	(PyTypeObject*)&PyObjCObject_Type, /* object_type */
103	&PyObjCSelector_Type,		/* select_type */
104	(RegisterMethodMappingFunctionType*)PyObjC_RegisterMethodMapping,	/* register_method_mapping */
105	(int (*)(char*, PyObject *(*)(PyObject*, PyObject*, PyObject*), void (*)(void*, void*, void**, void*)))PyObjC_RegisterSignatureMapping,	/* register_signature_mapping */
106	PyObjCObject_GetObject,		/* obj_get_object */
107	PyObjCObject_ClearObject,		/* obj_clear_object */
108	PyObjCClass_GetClass,		/* cls_get_class */
109	PyObjCClass_New,			/* cls_to_python */
110	python_to_id,			/* python_to_id */
111	id_to_python,			/* id_to_python */
112	PyObjCErr_FromObjC,		/* err_objc_to_python */
113	PyObjCErr_ToObjC,			/* err_python_to_objc */
114	depythonify_c_value,		/* py_to_objc */
115	pythonify_c_value,		/* objc_to_python */
116	PyObjCRT_SizeOfType,		/* sizeof_type */
117	sel_get_class,			/* sel_get_class */
118	sel_get_sel,			/* sel_get_sel */
119	fill_super,			/* fill_super */
120	fill_super_cls,			/* fill_super_cls*/
121	PyObjCPointerWrapper_Register,	/* register_pointer_wrapper */
122	(void(*)(void*,void*,void**,void*))PyObjCUnsupportedMethod_IMP,    /* unsupported_method_imp */
123	PyObjCUnsupportedMethod_Caller, /* unsupported_method_caller */
124	PyObjCErr_ToObjCWithGILState,	/* objc_err_to_objc_gil */
125	PyObjCRT_AlignOfType,		/* alignof_type */
126	sel_getName,			/* selname */
127	PyObjCRT_SimplifySignature,	/* simplify_sig */
128	PyObjC_FreeCArray,		/* free_c_array */
129	PyObjC_PythonToCArray,		/* py_to_c_array */
130	PyObjC_CArrayToPython,		/* c_array_to_py */
131	PyObjC_RegisterStructType,	/* register_struct */
132	&PyObjCIMP_Type,		/* imp_type */
133	PyObjCIMP_GetIMP,		/* imp_get_imp */
134	PyObjCIMP_GetSelector,		/* imp_get_sel */
135	PyObjCErr_AsExc,		/* err_python_to_nsexception */
136	PyGILState_Ensure,		/* gilstate_ensure */
137	obj_is_uninitialized,   /* obj_is_uninitialized */
138	PyObjCObject_Convert,   /* pyobjcobject_convert */
139	PyObjCSelector_Convert, /* pyobjcselector_convert */
140	PyObjCClass_Convert,    /* pyobjcclass_convert */
141	PyObjC_ConvertBOOL,     /* pyobjc_convertbool */
142	PyObjC_ConvertChar,     /* pyobjc_convertchar */
143	PyObjCObject_New,		/* pyobjc_object_new */
144	PyObjCCreateOpaquePointerType, /* pointer_type_new */
145	PyObjCObject_NewTransient,	/* newtransient */
146	PyObjCObject_ReleaseTransient,  /* releasetransient */
147	do_weaklink,			/* doweaklink */
148	PyObjCRT_RemoveFieldNames,	/* removefields */
149	&PyObjC_NULL,			/* PyObjC_NULL */
150	depythonify_c_array_count2,	/* PyObjC_DepythonifyCArray */
151	PyObjC_VarList_New,		/* PyObjC_VarList_New */
152};
153
154int PyObjCAPI_Register(PyObject* module)
155{
156	PyObject* API = PyCObject_FromVoidPtr(&objc_api, NULL);
157
158	if (API == NULL) return -1;
159
160	if (PyModule_AddObject(module, PYOBJC_API_NAME, API) < 0) {
161		Py_DECREF(API);
162		return -1;
163	}
164	return 0;
165}
166