2
pygame - Python Game Library
3
Copyright (C) 2000-2001 Pete Shinners
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with this library; if not, write to the Free
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
* SDL_RWops support for python objects
26
#define PYGAMEAPI_RWOBJECT_INTERNAL
38
PyThreadState* thread;
43
static int rw_seek(SDL_RWops* context, int offset, int whence);
44
static int rw_read(SDL_RWops* context, void* ptr, int size, int maxnum);
45
static int rw_write(SDL_RWops* context, const void* ptr, int size, int maxnum);
46
static int rw_close(SDL_RWops* context);
49
static int rw_seek_th(SDL_RWops* context, int offset, int whence);
50
static int rw_read_th(SDL_RWops* context, void* ptr, int size, int maxnum);
51
static int rw_write_th(SDL_RWops* context, const void* ptr, int size, int maxnum);
52
static int rw_close_th(SDL_RWops* context);
56
static SDL_RWops* get_standard_rwop(PyObject* obj)
58
if(PyString_Check(obj) || PyUnicode_Check(obj))
62
PyObject* tuple = PyTuple_New(1);
63
PyTuple_SET_ITEM(tuple, 0, obj);
65
if(!tuple) return NULL;
66
result = PyArg_ParseTuple(tuple, "s", &name);
70
return SDL_RWFromFile(name, "rb");
72
else if(PyFile_Check(obj))
73
return SDL_RWFromFP(PyFile_AsFile(obj), 1);
78
static void fetch_object_methods(RWHelper* helper, PyObject* obj)
80
helper->read = helper->write = helper->seek =
81
helper->tell = helper->close = NULL;
82
if(PyObject_HasAttrString(obj, "read"))
84
helper->read = PyObject_GetAttrString(obj, "read");
85
if(helper->read && !PyCallable_Check(helper->read))
88
if(PyObject_HasAttrString(obj, "write"))
90
helper->write = PyObject_GetAttrString(obj, "write");
91
if(helper->write && !PyCallable_Check(helper->write))
94
if(PyObject_HasAttrString(obj, "seek"))
96
helper->seek = PyObject_GetAttrString(obj, "seek");
97
if(helper->seek && !PyCallable_Check(helper->seek))
100
if(PyObject_HasAttrString(obj, "tell"))
102
helper->tell = PyObject_GetAttrString(obj, "tell");
103
if(helper->tell && !PyCallable_Check(helper->tell))
106
if(PyObject_HasAttrString(obj, "close"))
108
helper->close = PyObject_GetAttrString(obj, "close");
109
if(helper->close && !PyCallable_Check(helper->close))
110
helper->close = NULL;
115
static SDL_RWops* RWopsFromPython(PyObject* obj)
121
return (SDL_RWops*)RAISE(PyExc_TypeError, "Invalid filetype object");
122
rw = get_standard_rwop(obj);
126
helper = PyMem_New(RWHelper, 1);
127
fetch_object_methods(helper, obj);
130
rw->hidden.unknown.data1 = (void*)helper;
133
rw->write = rw_write;
134
rw->close = rw_close;
140
static int RWopsCheckPython(SDL_RWops* rw)
142
return rw->close == rw_close;
146
static int rw_seek(SDL_RWops* context, int offset, int whence)
148
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
152
if(!helper->seek || !helper->tell)
155
if(!(offset == 0 && whence == SEEK_CUR)) /*being called only for 'tell'*/
157
result = PyObject_CallFunction(helper->seek, "ii", offset, whence);
163
result = PyObject_CallFunction(helper->tell, NULL);
167
retval = PyInt_AsLong(result);
174
static int rw_read(SDL_RWops* context, void* ptr, int size, int maxnum)
176
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
183
result = PyObject_CallFunction(helper->read, "i", size * maxnum);
187
if(!PyString_Check(result))
193
retval = PyString_GET_SIZE(result);
194
memcpy(ptr, PyString_AsString(result), retval);
202
static int rw_write(SDL_RWops* context, const void* ptr, int size, int num)
204
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
210
result = PyObject_CallFunction(helper->write, "s#", ptr, size * num);
219
static int rw_close(SDL_RWops* context)
221
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
227
result = PyObject_CallFunction(helper->close, NULL);
233
Py_XDECREF(helper->seek);
234
Py_XDECREF(helper->tell);
235
Py_XDECREF(helper->write);
236
Py_XDECREF(helper->read);
237
Py_XDECREF(helper->close);
248
static SDL_RWops* RWopsFromPythonThreaded(PyObject* obj)
252
PyInterpreterState* interp;
253
PyThreadState* thread;
256
return (SDL_RWops*)RAISE(PyExc_TypeError, "Invalid filetype object");
258
rw = get_standard_rwop(obj);
263
return (SDL_RWops*)RAISE(PyExc_NotImplementedError, "Python built without thread support");
265
helper = PyMem_New(RWHelper, 1);
266
fetch_object_methods(helper, obj);
269
rw->hidden.unknown.data1 = (void*)helper;
270
rw->seek = rw_seek_th;
271
rw->read = rw_read_th;
272
rw->write = rw_write_th;
273
rw->close = rw_close_th;
275
PyEval_InitThreads();
276
thread = PyThreadState_Get();
277
interp = thread->interp;
278
helper->thread = PyThreadState_New(interp);
285
static int RWopsCheckPythonThreaded(SDL_RWops* rw)
288
return rw->close == rw_close_th;
295
static int rw_seek_th(SDL_RWops* context, int offset, int whence)
297
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
300
PyThreadState* oldstate;
302
if(!helper->seek || !helper->tell)
305
PyEval_AcquireLock();
306
oldstate = PyThreadState_Swap(helper->thread);
308
if(!(offset == 0 && whence == SEEK_CUR)) /*being called only for 'tell'*/
310
result = PyObject_CallFunction(helper->seek, "ii", offset, whence);
316
result = PyObject_CallFunction(helper->tell, NULL);
320
retval = PyInt_AsLong(result);
323
PyThreadState_Swap(oldstate);
324
PyEval_ReleaseLock();
330
static int rw_read_th(SDL_RWops* context, void* ptr, int size, int maxnum)
332
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
335
PyThreadState* oldstate;
340
PyEval_AcquireLock();
341
oldstate = PyThreadState_Swap(helper->thread);
343
result = PyObject_CallFunction(helper->read, "i", size * maxnum);
347
if(!PyString_Check(result))
353
retval = PyString_GET_SIZE(result);
354
memcpy(ptr, PyString_AsString(result), retval);
359
PyThreadState_Swap(oldstate);
360
PyEval_ReleaseLock();
366
static int rw_write_th(SDL_RWops* context, const void* ptr, int size, int num)
368
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
370
PyThreadState* oldstate;
375
PyEval_AcquireLock();
376
oldstate = PyThreadState_Swap(helper->thread);
378
result = PyObject_CallFunction(helper->write, "s#", ptr, size * num);
384
PyThreadState_Swap(oldstate);
385
PyEval_ReleaseLock();
391
static int rw_close_th(SDL_RWops* context)
393
RWHelper* helper = (RWHelper*)context->hidden.unknown.data1;
396
PyThreadState* oldstate;
398
PyEval_AcquireLock();
399
oldstate = PyThreadState_Swap(helper->thread);
403
result = PyObject_CallFunction(helper->close, NULL);
409
Py_XDECREF(helper->seek);
410
Py_XDECREF(helper->tell);
411
Py_XDECREF(helper->write);
412
Py_XDECREF(helper->read);
413
Py_XDECREF(helper->close);
416
PyThreadState_Swap(oldstate);
417
PyThreadState_Clear(helper->thread);
418
PyThreadState_Delete(helper->thread);
419
PyEval_ReleaseLock();
428
static PyMethodDef rwobject__builtins__[] =
436
void initrwobject(void)
438
PyObject *module, *dict, *apiobj;
439
static void* c_api[PYGAMEAPI_RWOBJECT_NUMSLOTS];
441
PyGAME_C_API[0] = PyGAME_C_API[0]; /*this cleans a compiler warning*/
443
/* Create the module and add the functions */
444
module = Py_InitModule3("rwobject", rwobject__builtins__, "SDL_RWops support");
445
dict = PyModule_GetDict(module);
447
/* export the c api */
448
c_api[0] = RWopsFromPython;
449
c_api[1] = RWopsCheckPython;
450
c_api[2] = RWopsFromPythonThreaded;
451
c_api[3] = RWopsCheckPythonThreaded;
452
apiobj = PyCObject_FromVoidPtr(c_api, NULL);
453
PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);