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
17
18static void do_weaklink(PyObject* module_dict, struct PyObjC_WeakLink* funcs)
19{
20	while (funcs->name) {
21		if (!funcs->func) {
22			if (PyDict_DelItemString(
23					module_dict,
24					funcs->name) == -1) {
25				PyErr_Clear();
26			}
27		}
28		funcs++;
29	}
30}
31
32static int obj_is_uninitialized(PyObject* object)
33{
34	if (!PyObjCObject_Check(object)) {
35		return -1;
36	}
37	return (PyObjCObject_GetFlags(object) & PyObjCObject_kUNINITIALIZED) != 0;
38}
39
40static id python_to_id(PyObject* object)
41{
42	id result;
43	int err;
44
45	err = depythonify_c_value(@encode(id), object, &result);
46	if (err == -1) {
47		return nil;
48	}
49
50	return result;
51}
52
53static PyObject* id_to_python(id object)
54{
55	PyObject* result;
56
57	result = pythonify_c_value(@encode(id), &object);
58	return result;
59}
60
61static Class      sel_get_class(PyObject* sel)
62{
63	if (!PyObjCNativeSelector_Check(sel)) {
64		PyErr_SetString(PyExc_TypeError, "Expecting PyObjCSelector");
65		return NULL;
66	}
67	return ((PyObjCNativeSelector*)sel)->sel_class;
68}
69
70static SEL      sel_get_sel(PyObject* sel)
71{
72	if (!PyObjCSelector_Check(sel)) {
73		PyErr_SetString(PyExc_TypeError, "Expecting PyObjCSelector");
74		return NULL;
75	}
76	return ((PyObjCSelector*)sel)->sel_selector;
77}
78
79static void 	fill_super(struct objc_super* super, Class cls, id receiver)
80{
81	objc_superSetReceiver(*super, receiver);
82	objc_superSetClass(*super, cls);
83}
84
85static void 	fill_super_cls(struct objc_super* super, Class cls, Class self)
86{
87	objc_superSetReceiver(*super, self);
88	objc_superSetClass(*super, object_getClass(cls));
89}
90
91static int depythonify_c_array_count2(const char* type, Py_ssize_t count, BOOL strict, PyObject* value, void* datum)
92{
93	return depythonify_c_array_count(type, count, strict, value, datum, NO, NO);
94}
95
96
97
98
99struct pyobjc_api objc_api = {
100	PYOBJC_API_VERSION,		/* api_version */
101	sizeof(struct pyobjc_api),	/* struct_size */
102	&PyObjCClass_Type,		/* class_type */
103	(PyTypeObject*)&PyObjCObject_Type, /* object_type */
104	&PyObjCSelector_Type,		/* select_type */
105	(RegisterMethodMappingFunctionType*)PyObjC_RegisterMethodMapping,	/* register_method_mapping */
106	(int (*)(char*, PyObject *(*)(PyObject*, PyObject*, PyObject*), void (*)(void*, void*, void**, void*)))PyObjC_RegisterSignatureMapping,	/* register_signature_mapping */
107	PyObjCObject_GetObject,		/* obj_get_object */
108	PyObjCObject_ClearObject,		/* obj_clear_object */
109	PyObjCClass_GetClass,		/* cls_get_class */
110	PyObjCClass_New,			/* cls_to_python */
111	python_to_id,			/* python_to_id */
112	id_to_python,			/* id_to_python */
113	PyObjCErr_FromObjC,		/* err_objc_to_python */
114	PyObjCErr_ToObjC,			/* err_python_to_objc */
115	depythonify_c_value,		/* py_to_objc */
116	pythonify_c_value,		/* objc_to_python */
117	PyObjCRT_SizeOfType,		/* sizeof_type */
118	sel_get_class,			/* sel_get_class */
119	sel_get_sel,			/* sel_get_sel */
120	fill_super,			/* fill_super */
121	fill_super_cls,			/* fill_super_cls*/
122	PyObjCPointerWrapper_Register,	/* register_pointer_wrapper */
123	(void(*)(void*,void*,void**,void*))PyObjCUnsupportedMethod_IMP,    /* unsupported_method_imp */
124	PyObjCUnsupportedMethod_Caller, /* unsupported_method_caller */
125	PyObjCErr_ToObjCWithGILState,	/* objc_err_to_objc_gil */
126	PyObjCRT_AlignOfType,		/* alignof_type */
127	sel_getName,			/* selname */
128	PyObjCRT_SimplifySignature,	/* simplify_sig */
129	PyObjC_FreeCArray,		/* free_c_array */
130	PyObjC_PythonToCArray,		/* py_to_c_array */
131	PyObjC_CArrayToPython,		/* c_array_to_py */
132	PyObjC_RegisterStructType,	/* register_struct */
133	&PyObjCIMP_Type,		/* imp_type */
134	PyObjCIMP_GetIMP,		/* imp_get_imp */
135	PyObjCIMP_GetSelector,		/* imp_get_sel */
136	PyObjCErr_AsExc,		/* err_python_to_nsexception */
137	PyGILState_Ensure,		/* gilstate_ensure */
138	obj_is_uninitialized,   /* obj_is_uninitialized */
139	PyObjCObject_New,		/* pyobjc_object_new */
140	PyObjCCreateOpaquePointerType, /* pointer_type_new */
141	PyObjCObject_NewTransient,	/* newtransient */
142	PyObjCObject_ReleaseTransient,  /* releasetransient */
143	do_weaklink,			/* doweaklink */
144	PyObjCRT_RemoveFieldNames,	/* removefields */
145	&PyObjC_NULL,			/* PyObjC_NULL */
146	depythonify_c_array_count2,	/* PyObjC_DepythonifyCArray */
147	PyObjC_VarList_New,		/* PyObjC_VarList_New */
148	PyObjC_is_ascii_string,
149	PyObjC_is_ascii_prefix,
150	PyObjCObject_Convert,
151};
152
153int PyObjCAPI_Register(PyObject* module)
154{
155#if PY_MAJOR_VERSION == 2
156	PyObject* API = PyCObject_FromVoidPtr(&objc_api, NULL);
157#else
158	PyObject* API = PyCapsule_New(&objc_api, "objc." PYOBJC_API_NAME, NULL);
159#endif
160
161	if (API == NULL) return -1;
162
163	if (PyModule_AddObject(module, PYOBJC_API_NAME, API) < 0) {
164		Py_DECREF(API);
165		return -1;
166	}
167	return 0;
168}
169