blob: 34c46ad7a7eeaacbb95435121c2c14adaa91eb07 [file] [log] [blame]
Thomas Hellerd4c93202006-03-08 19:35:11 +00001#include "Python.h"
Thomas Hellerd4c93202006-03-08 19:35:11 +00002#include "frameobject.h"
3
4#include <ffi.h>
5#ifdef MS_WIN32
6#include <windows.h>
7#endif
8#include "ctypes.h"
9
Thomas Hellere106dc32008-04-24 18:39:36 +000010/**************************************************************/
11
Thomas Hellerb041fda2008-04-30 17:11:46 +000012static void
13CThunkObject_dealloc(PyObject *_self)
Thomas Hellere106dc32008-04-24 18:39:36 +000014{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000015 CThunkObject *self = (CThunkObject *)_self;
Amaury Forgeot d'Arcbbe46d62011-09-12 21:03:36 +020016 PyObject_GC_UnTrack(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000017 Py_XDECREF(self->converters);
18 Py_XDECREF(self->callable);
19 Py_XDECREF(self->restype);
Thomas Heller864cc672010-08-08 17:58:53 +000020 if (self->pcl_write)
21 ffi_closure_free(self->pcl_write);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 PyObject_GC_Del(self);
Thomas Hellere106dc32008-04-24 18:39:36 +000023}
24
25static int
26CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg)
27{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 CThunkObject *self = (CThunkObject *)_self;
29 Py_VISIT(self->converters);
30 Py_VISIT(self->callable);
31 Py_VISIT(self->restype);
32 return 0;
Thomas Hellere106dc32008-04-24 18:39:36 +000033}
34
35static int
36CThunkObject_clear(PyObject *_self)
37{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 CThunkObject *self = (CThunkObject *)_self;
39 Py_CLEAR(self->converters);
40 Py_CLEAR(self->callable);
41 Py_CLEAR(self->restype);
42 return 0;
Thomas Hellere106dc32008-04-24 18:39:36 +000043}
44
Thomas Heller34596a92009-04-24 20:50:00 +000045PyTypeObject PyCThunk_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000046 PyVarObject_HEAD_INIT(NULL, 0)
47 "_ctypes.CThunkObject",
48 sizeof(CThunkObject), /* tp_basicsize */
49 sizeof(ffi_type), /* tp_itemsize */
50 CThunkObject_dealloc, /* tp_dealloc */
51 0, /* tp_print */
52 0, /* tp_getattr */
53 0, /* tp_setattr */
54 0, /* tp_reserved */
55 0, /* tp_repr */
56 0, /* tp_as_number */
57 0, /* tp_as_sequence */
58 0, /* tp_as_mapping */
59 0, /* tp_hash */
60 0, /* tp_call */
61 0, /* tp_str */
62 0, /* tp_getattro */
63 0, /* tp_setattro */
64 0, /* tp_as_buffer */
65 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
66 "CThunkObject", /* tp_doc */
67 CThunkObject_traverse, /* tp_traverse */
68 CThunkObject_clear, /* tp_clear */
69 0, /* tp_richcompare */
70 0, /* tp_weaklistoffset */
71 0, /* tp_iter */
72 0, /* tp_iternext */
73 0, /* tp_methods */
74 0, /* tp_members */
Thomas Hellere106dc32008-04-24 18:39:36 +000075};
76
77/**************************************************************/
78
Thomas Hellerd4c93202006-03-08 19:35:11 +000079static void
80PrintError(char *msg, ...)
81{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 char buf[512];
83 PyObject *f = PySys_GetObject("stderr");
84 va_list marker;
Thomas Hellerd4c93202006-03-08 19:35:11 +000085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 va_start(marker, msg);
87 vsnprintf(buf, sizeof(buf), msg, marker);
88 va_end(marker);
89 if (f != NULL && f != Py_None)
90 PyFile_WriteString(buf, f);
91 PyErr_Print();
Thomas Hellerd4c93202006-03-08 19:35:11 +000092}
93
94
95/* after code that pyrex generates */
Thomas Heller34596a92009-04-24 20:50:00 +000096void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
Thomas Hellerd4c93202006-03-08 19:35:11 +000097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 PyObject *py_globals = 0;
99 PyCodeObject *py_code = 0;
100 PyFrameObject *py_frame = 0;
101
102 py_globals = PyDict_New();
103 if (!py_globals) goto bad;
104 py_code = PyCode_NewEmpty(filename, funcname, lineno);
105 if (!py_code) goto bad;
106 py_frame = PyFrame_New(
107 PyThreadState_Get(), /*PyThreadState *tstate,*/
108 py_code, /*PyCodeObject *code,*/
109 py_globals, /*PyObject *globals,*/
110 0 /*PyObject *locals*/
111 );
112 if (!py_frame) goto bad;
113 py_frame->f_lineno = lineno;
114 PyTraceBack_Here(py_frame);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000115 bad:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 Py_XDECREF(py_globals);
117 Py_XDECREF(py_code);
118 Py_XDECREF(py_frame);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000119}
120
121#ifdef MS_WIN32
122/*
123 * We must call AddRef() on non-NULL COM pointers we receive as arguments
124 * to callback functions - these functions are COM method implementations.
125 * The Python instances we create have a __del__ method which calls Release().
126 *
127 * The presence of a class attribute named '_needs_com_addref_' triggers this
128 * behaviour. It would also be possible to call the AddRef() Python method,
129 * after checking for PyObject_IsTrue(), but this would probably be somewhat
130 * slower.
131 */
132static void
133TryAddRef(StgDictObject *dict, CDataObject *obj)
134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 IUnknown *punk;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000136
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 if (NULL == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_"))
138 return;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 punk = *(IUnknown **)obj->b_ptr;
141 if (punk)
142 punk->lpVtbl->AddRef(punk);
143 return;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000144}
145#endif
146
147/******************************************************************************
148 *
149 * Call the python object with all arguments
150 *
151 */
152static void _CallPythonObject(void *mem,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 ffi_type *restype,
154 SETFUNC setfunc,
155 PyObject *callable,
156 PyObject *converters,
157 int flags,
158 void **pArgs)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000159{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 Py_ssize_t i;
161 PyObject *result;
162 PyObject *arglist = NULL;
163 Py_ssize_t nArgs;
164 PyObject *error_object = NULL;
165 int *space;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000166#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 PyGILState_STATE state = PyGILState_Ensure();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000168#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +0000169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 nArgs = PySequence_Length(converters);
171 /* Hm. What to return in case of error?
172 For COM, 0xFFFFFFFF seems better than 0.
173 */
174 if (nArgs < 0) {
175 PrintError("BUG: PySequence_Length");
176 goto Done;
177 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 arglist = PyTuple_New(nArgs);
180 if (!arglist) {
181 PrintError("PyTuple_New()");
182 goto Done;
183 }
184 for (i = 0; i < nArgs; ++i) {
185 /* Note: new reference! */
186 PyObject *cnv = PySequence_GetItem(converters, i);
187 StgDictObject *dict;
188 if (cnv)
189 dict = PyType_stgdict(cnv);
190 else {
191 PrintError("Getting argument converter %d\n", i);
192 goto Done;
193 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) {
196 PyObject *v = dict->getfunc(*pArgs, dict->size);
197 if (!v) {
198 PrintError("create argument %d:\n", i);
199 Py_DECREF(cnv);
200 goto Done;
201 }
202 PyTuple_SET_ITEM(arglist, i, v);
203 /* XXX XXX XX
204 We have the problem that c_byte or c_short have dict->size of
205 1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
Ezio Melotti13925002011-03-16 11:05:33 +0200206 BTW, the same problem occurs when they are pushed as parameters
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 */
208 } else if (dict) {
209 /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
210 CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL);
211 if (!obj) {
212 PrintError("create argument %d:\n", i);
213 Py_DECREF(cnv);
214 goto Done;
215 }
216 if (!CDataObject_Check(obj)) {
217 Py_DECREF(obj);
218 Py_DECREF(cnv);
219 PrintError("unexpected result of create argument %d:\n", i);
220 goto Done;
221 }
222 memcpy(obj->b_ptr, *pArgs, dict->size);
223 PyTuple_SET_ITEM(arglist, i, (PyObject *)obj);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000224#ifdef MS_WIN32
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 TryAddRef(dict, obj);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000226#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 } else {
228 PyErr_SetString(PyExc_TypeError,
229 "cannot build parameter");
230 PrintError("Parsing argument %d\n", i);
231 Py_DECREF(cnv);
232 goto Done;
233 }
234 Py_DECREF(cnv);
235 /* XXX error handling! */
236 pArgs++;
237 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000238
239#define CHECK(what, x) \
Thomas Heller34596a92009-04-24 20:50:00 +0000240if (x == NULL) _ctypes_add_traceback(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print()
Thomas Hellerd4c93202006-03-08 19:35:11 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
243 error_object = _ctypes_get_errobj(&space);
244 if (error_object == NULL)
245 goto Done;
246 if (flags & FUNCFLAG_USE_ERRNO) {
247 int temp = space[0];
248 space[0] = errno;
249 errno = temp;
250 }
Thomas Heller9cac7b62008-06-06 09:31:40 +0000251#ifdef MS_WIN32
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252 if (flags & FUNCFLAG_USE_LASTERROR) {
253 int temp = space[1];
254 space[1] = GetLastError();
255 SetLastError(temp);
256 }
Thomas Heller9cac7b62008-06-06 09:31:40 +0000257#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 }
Thomas Heller9cac7b62008-06-06 09:31:40 +0000259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 result = PyObject_CallObject(callable, arglist);
261 CHECK("'calling callback function'", result);
Thomas Heller9cac7b62008-06-06 09:31:40 +0000262
263#ifdef MS_WIN32
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 if (flags & FUNCFLAG_USE_LASTERROR) {
265 int temp = space[1];
266 space[1] = GetLastError();
267 SetLastError(temp);
268 }
Thomas Heller9cac7b62008-06-06 09:31:40 +0000269#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 if (flags & FUNCFLAG_USE_ERRNO) {
271 int temp = space[0];
272 space[0] = errno;
273 errno = temp;
274 }
275 Py_XDECREF(error_object);
Thomas Heller9cac7b62008-06-06 09:31:40 +0000276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 if ((restype != &ffi_type_void) && result) {
278 PyObject *keep;
279 assert(setfunc);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000280#ifdef WORDS_BIGENDIAN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 /* See the corresponding code in callproc.c, around line 961 */
282 if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg))
283 mem = (char *)mem + sizeof(ffi_arg) - restype->size;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000284#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 keep = setfunc(mem, result, 0);
286 CHECK("'converting callback result'", keep);
287 /* keep is an object we have to keep alive so that the result
288 stays valid. If there is no such object, the setfunc will
289 have returned Py_None.
Thomas Hellerd4c93202006-03-08 19:35:11 +0000290
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 If there is such an object, we have no choice than to keep
292 it alive forever - but a refcount and/or memory leak will
293 be the result. EXCEPT when restype is py_object - Python
294 itself knows how to manage the refcount of these objects.
295 */
296 if (keep == NULL) /* Could not convert callback result. */
297 PyErr_WriteUnraisable(callable);
298 else if (keep == Py_None) /* Nothing to keep */
299 Py_DECREF(keep);
300 else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
301 if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning,
302 "memory leak in callback function.",
303 1))
304 PyErr_WriteUnraisable(callable);
305 }
306 }
307 Py_XDECREF(result);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000308 Done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000309 Py_XDECREF(arglist);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000310#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 PyGILState_Release(state);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000312#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +0000313}
314
Thomas Hellerd4c93202006-03-08 19:35:11 +0000315static void closure_fcn(ffi_cif *cif,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 void *resp,
317 void **args,
318 void *userdata)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000319{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 CThunkObject *p = (CThunkObject *)userdata;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322 _CallPythonObject(resp,
323 p->ffi_restype,
324 p->setfunc,
325 p->callable,
326 p->converters,
327 p->flags,
328 args);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000329}
330
Thomas Hellere106dc32008-04-24 18:39:36 +0000331static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 CThunkObject *p;
334 int i;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
337 if (p == NULL) {
338 PyErr_NoMemory();
339 return NULL;
340 }
Thomas Hellere106dc32008-04-24 18:39:36 +0000341
Thomas Heller864cc672010-08-08 17:58:53 +0000342 p->pcl_exec = NULL;
343 p->pcl_write = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000344 memset(&p->cif, 0, sizeof(p->cif));
345 p->converters = NULL;
346 p->callable = NULL;
347 p->setfunc = NULL;
348 p->ffi_restype = NULL;
349
350 for (i = 0; i < nArgs + 1; ++i)
351 p->atypes[i] = NULL;
352 PyObject_GC_Track((PyObject *)p);
353 return p;
Thomas Hellere106dc32008-04-24 18:39:36 +0000354}
355
Thomas Heller34596a92009-04-24 20:50:00 +0000356CThunkObject *_ctypes_alloc_callback(PyObject *callable,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 PyObject *converters,
358 PyObject *restype,
359 int flags)
Thomas Hellere106dc32008-04-24 18:39:36 +0000360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361 int result;
362 CThunkObject *p;
363 Py_ssize_t nArgs, i;
364 ffi_abi cc;
Thomas Hellere106dc32008-04-24 18:39:36 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366 nArgs = PySequence_Size(converters);
367 p = CThunkObject_new(nArgs);
368 if (p == NULL)
369 return NULL;
Thomas Hellere106dc32008-04-24 18:39:36 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 assert(CThunk_CheckExact((PyObject *)p));
Thomas Hellere106dc32008-04-24 18:39:36 +0000372
Thomas Heller864cc672010-08-08 17:58:53 +0000373 p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
374 &p->pcl_exec);
375 if (p->pcl_write == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 PyErr_NoMemory();
377 goto error;
378 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 p->flags = flags;
381 for (i = 0; i < nArgs; ++i) {
382 PyObject *cnv = PySequence_GetItem(converters, i);
383 if (cnv == NULL)
384 goto error;
385 p->atypes[i] = _ctypes_get_ffi_type(cnv);
386 Py_DECREF(cnv);
387 }
388 p->atypes[i] = NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 Py_INCREF(restype);
391 p->restype = restype;
392 if (restype == Py_None) {
393 p->setfunc = NULL;
394 p->ffi_restype = &ffi_type_void;
395 } else {
396 StgDictObject *dict = PyType_stgdict(restype);
397 if (dict == NULL || dict->setfunc == NULL) {
398 PyErr_SetString(PyExc_TypeError,
399 "invalid result type for callback function");
400 goto error;
401 }
402 p->setfunc = dict->setfunc;
403 p->ffi_restype = &dict->ffi_type_pointer;
404 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 cc = FFI_DEFAULT_ABI;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000407#if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 if ((flags & FUNCFLAG_CDECL) == 0)
409 cc = FFI_STDCALL;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000410#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 result = ffi_prep_cif(&p->cif, cc,
412 Py_SAFE_DOWNCAST(nArgs, Py_ssize_t, int),
413 _ctypes_get_ffi_type(restype),
414 &p->atypes[0]);
415 if (result != FFI_OK) {
416 PyErr_Format(PyExc_RuntimeError,
417 "ffi_prep_cif failed with %d", result);
418 goto error;
419 }
Ronald Oussoren2decf222010-09-05 18:25:59 +0000420#if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
421 result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
422#else
Thomas Heller864cc672010-08-08 17:58:53 +0000423 result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
424 p,
425 p->pcl_exec);
Ronald Oussoren2decf222010-09-05 18:25:59 +0000426#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 if (result != FFI_OK) {
428 PyErr_Format(PyExc_RuntimeError,
429 "ffi_prep_closure failed with %d", result);
430 goto error;
431 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 Py_INCREF(converters);
434 p->converters = converters;
435 Py_INCREF(callable);
436 p->callable = callable;
437 return p;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000438
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000439 error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 Py_XDECREF(p);
441 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000442}
443
Thomas Hellerd4c93202006-03-08 19:35:11 +0000444#ifdef MS_WIN32
445
446static void LoadPython(void)
447{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 if (!Py_IsInitialized()) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000449#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 PyEval_InitThreads();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000451#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 Py_Initialize();
453 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000454}
455
456/******************************************************************/
457
458long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
459{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 PyObject *mod, *func, *result;
461 long retval;
462 static PyObject *context;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 if (context == NULL)
465 context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
Thomas Hellerd4c93202006-03-08 19:35:11 +0000466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000467 mod = PyImport_ImportModuleNoBlock("ctypes");
468 if (!mod) {
469 PyErr_WriteUnraisable(context ? context : Py_None);
470 /* There has been a warning before about this already */
471 return E_FAIL;
472 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474 func = PyObject_GetAttrString(mod, "DllGetClassObject");
475 Py_DECREF(mod);
476 if (!func) {
477 PyErr_WriteUnraisable(context ? context : Py_None);
478 return E_FAIL;
479 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 {
482 PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
483 PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
484 PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
485 if (!py_rclsid || !py_riid || !py_ppv) {
486 Py_XDECREF(py_rclsid);
487 Py_XDECREF(py_riid);
488 Py_XDECREF(py_ppv);
489 Py_DECREF(func);
490 PyErr_WriteUnraisable(context ? context : Py_None);
491 return E_FAIL;
492 }
493 result = PyObject_CallFunctionObjArgs(func,
494 py_rclsid,
495 py_riid,
496 py_ppv,
497 NULL);
498 Py_DECREF(py_rclsid);
499 Py_DECREF(py_riid);
500 Py_DECREF(py_ppv);
501 }
502 Py_DECREF(func);
503 if (!result) {
504 PyErr_WriteUnraisable(context ? context : Py_None);
505 return E_FAIL;
506 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 retval = PyLong_AsLong(result);
509 if (PyErr_Occurred()) {
510 PyErr_WriteUnraisable(context ? context : Py_None);
511 retval = E_FAIL;
512 }
513 Py_DECREF(result);
514 return retval;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000515}
516
517STDAPI DllGetClassObject(REFCLSID rclsid,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 REFIID riid,
519 LPVOID *ppv)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000520{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 long result;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000522#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 PyGILState_STATE state;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000524#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +0000525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 LoadPython();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000527#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 state = PyGILState_Ensure();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000529#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 result = Call_GetClassObject(rclsid, riid, ppv);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 PyGILState_Release(state);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000533#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 return result;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000535}
536
537long Call_CanUnloadNow(void)
538{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 PyObject *mod, *func, *result;
540 long retval;
541 static PyObject *context;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000542
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 if (context == NULL)
544 context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow");
Thomas Hellerd4c93202006-03-08 19:35:11 +0000545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 mod = PyImport_ImportModuleNoBlock("ctypes");
547 if (!mod) {
548/* OutputDebugString("Could not import ctypes"); */
549 /* We assume that this error can only occur when shutting
550 down, so we silently ignore it */
551 PyErr_Clear();
552 return E_FAIL;
553 }
554 /* Other errors cannot be raised, but are printed to stderr */
555 func = PyObject_GetAttrString(mod, "DllCanUnloadNow");
556 Py_DECREF(mod);
557 if (!func) {
558 PyErr_WriteUnraisable(context ? context : Py_None);
559 return E_FAIL;
560 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 result = PyObject_CallFunction(func, NULL);
563 Py_DECREF(func);
564 if (!result) {
565 PyErr_WriteUnraisable(context ? context : Py_None);
566 return E_FAIL;
567 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 retval = PyLong_AsLong(result);
570 if (PyErr_Occurred()) {
571 PyErr_WriteUnraisable(context ? context : Py_None);
572 retval = E_FAIL;
573 }
574 Py_DECREF(result);
575 return retval;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000576}
577
578/*
579 DllRegisterServer and DllUnregisterServer still missing
580*/
581
582STDAPI DllCanUnloadNow(void)
583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 long result;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000585#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 PyGILState_STATE state = PyGILState_Ensure();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000587#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 result = Call_CanUnloadNow();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000589#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 PyGILState_Release(state);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000591#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 return result;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000593}
594
595#ifndef Py_NO_ENABLE_SHARED
596BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes)
597{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 switch(fdwReason) {
599 case DLL_PROCESS_ATTACH:
600 DisableThreadLibraryCalls(hinstDLL);
601 break;
602 }
603 return TRUE;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000604}
605#endif
606
607#endif
608
609/*
610 Local Variables:
611 compile-command: "cd .. && python setup.py -q build_ext"
612 End:
613*/