+ else
+ return wxInvalidOffset;
+}
+
+
+size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
+ if (bufsize == 0)
+ return 0;
+
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ PyObject* arglist = Py_BuildValue("(i)", bufsize);
+ PyObject* result = PyEval_CallObject(m_read, arglist);
+ Py_DECREF(arglist);
+
+ size_t o = 0;
+ if ((result != NULL) && PyString_Check(result)) {
+ o = PyString_Size(result);
+ if (o == 0)
+ m_lasterror = wxSTREAM_EOF;
+ if (o > bufsize)
+ o = bufsize;
+ memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode...
+ Py_DECREF(result);
+
+ }
+ else
+ m_lasterror = wxSTREAM_READ_ERROR;
+ wxPyEndBlockThreads(blocked);
+ return o;
+}
+
+size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) {
+ m_lasterror = wxSTREAM_WRITE_ERROR;
+ return 0;
+}
+
+
+wxFileOffset wxPyCBInputStream::OnSysSeek(wxFileOffset off, wxSeekMode mode) {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ PyObject* arglist = PyTuple_New(2);
+
+ if (sizeof(wxFileOffset) > sizeof(long))
+ // wxFileOffset is a 64-bit value...
+ PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
+ else
+ PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off));
+
+ PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode));
+
+
+ PyObject* result = PyEval_CallObject(m_seek, arglist);
+ Py_DECREF(arglist);
+ Py_XDECREF(result);
+ wxPyEndBlockThreads(blocked);
+ return OnSysTell();
+}
+
+
+wxFileOffset wxPyCBInputStream::OnSysTell() const {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ PyObject* arglist = Py_BuildValue("()");
+ PyObject* result = PyEval_CallObject(m_tell, arglist);
+ Py_DECREF(arglist);
+ wxFileOffset o = 0;
+ if (result != NULL) {
+ if (PyLong_Check(result))
+ o = PyLong_AsLongLong(result);
+ else
+ o = PyInt_AsLong(result);
+ Py_DECREF(result);
+ };
+ wxPyEndBlockThreads(blocked);
+ return o;
+}
+
+//----------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
+
+wxPyCallback::wxPyCallback(PyObject* func) {
+ m_func = func;
+ Py_INCREF(m_func);
+}
+
+wxPyCallback::wxPyCallback(const wxPyCallback& other) {
+ m_func = other.m_func;
+ Py_INCREF(m_func);
+}
+
+wxPyCallback::~wxPyCallback() {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ Py_DECREF(m_func);
+ wxPyEndBlockThreads(blocked);
+}
+
+
+#define wxPy_PRECALLINIT "_preCallInit"
+#define wxPy_POSTCALLCLEANUP "_postCallCleanup"
+
+// This function is used for all events destined for Python event handlers.
+void wxPyCallback::EventThunker(wxEvent& event) {
+ wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
+ PyObject* func = cb->m_func;
+ PyObject* result;
+ PyObject* arg;
+ PyObject* tuple;
+ bool checkSkip = false;
+
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ wxString className = event.GetClassInfo()->GetClassName();
+
+ // If the event is one of these types then pass the original
+ // event object instead of the one passed to us.
+ if ( className == wxT("wxPyEvent") ) {
+ arg = ((wxPyEvent*)&event)->GetSelf();
+ checkSkip = ((wxPyEvent*)&event)->GetCloned();
+ }
+ else if ( className == wxT("wxPyCommandEvent") ) {
+ arg = ((wxPyCommandEvent*)&event)->GetSelf();
+ checkSkip = ((wxPyCommandEvent*)&event)->GetCloned();
+ }
+ else {
+ arg = wxPyConstructObject((void*)&event, className);
+ }
+
+ if (!arg) {
+ PyErr_Print();
+ } else {
+ // "intern" the pre/post method names to speed up the HasAttr
+ static PyObject* s_preName = NULL;
+ static PyObject* s_postName = NULL;
+ if (s_preName == NULL) {
+ s_preName = PyString_FromString(wxPy_PRECALLINIT);
+ s_postName = PyString_FromString(wxPy_POSTCALLCLEANUP);
+ }
+
+ // Check if the event object needs some preinitialization
+ if (PyObject_HasAttr(arg, s_preName)) {
+ result = PyObject_CallMethodObjArgs(arg, s_preName, arg, NULL);
+ if ( result ) {
+ Py_DECREF(result); // result is ignored, but we still need to decref it
+ PyErr_Clear(); // Just in case...
+ } else {
+ PyErr_Print();
+ }
+ }
+
+ // Call the event handler, passing the event object
+ tuple = PyTuple_New(1);
+ PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg
+ result = PyEval_CallObject(func, tuple);
+ if ( result ) {
+ Py_DECREF(result); // result is ignored, but we still need to decref it
+ PyErr_Clear(); // Just in case...
+ } else {
+ PyErr_Print();
+ }
+
+ // Check if the event object needs some post cleanup
+ if (PyObject_HasAttr(arg, s_postName)) {
+ result = PyObject_CallMethodObjArgs(arg, s_postName, arg, NULL);
+ if ( result ) {
+ Py_DECREF(result); // result is ignored, but we still need to decref it
+ PyErr_Clear(); // Just in case...
+ } else {
+ PyErr_Print();
+ }
+ }
+
+ if ( checkSkip ) {
+ // if the event object was one of our special types and
+ // it had been cloned, then we need to extract the Skipped
+ // value from the original and set it in the clone.
+ result = PyObject_CallMethod(arg, "GetSkipped", "");
+ if ( result ) {
+ event.Skip(PyInt_AsLong(result));
+ Py_DECREF(result);
+ } else {
+ PyErr_Print();
+ }
+ }
+ Py_DECREF(tuple);
+ }
+ wxPyEndBlockThreads(blocked);
+}
+
+
+//----------------------------------------------------------------------
+
+wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
+ m_lastFound = NULL;
+ m_self = other.m_self;
+ m_class = other.m_class;
+ if (m_self) {
+ Py_INCREF(m_self);
+ Py_INCREF(m_class);
+ }
+}
+
+
+void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
+ m_self = self;
+ m_class = klass;
+ m_incRef = incref;
+ if (incref) {
+ Py_INCREF(m_self);
+ Py_INCREF(m_class);
+ }
+}
+
+
+#if PYTHON_API_VERSION >= 1011
+
+// Prior to Python 2.2 PyMethod_GetClass returned the class object
+// in which the method was defined. Starting with 2.2 it returns
+// "class that asked for the method" which seems totally bogus to me
+// but apprently it fixes some obscure problem waiting to happen in
+// Python. Since the API was not documented Guido and the gang felt
+// safe in changing it. Needless to say that totally screwed up the
+// logic below in wxPyCallbackHelper::findCallback, hence this icky
+// code to find the class where the method is actually defined...
+
+static
+PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name)
+{
+ int i, n;
+
+ if (PyType_Check(klass)) { // new style classes
+ // This code is borrowed/adapted from _PyType_Lookup in typeobject.c
+ PyTypeObject* type = (PyTypeObject*)klass;
+ PyObject *mro, *res, *base, *dict;
+ /* Look in tp_dict of types in MRO */
+ mro = type->tp_mro;
+ assert(PyTuple_Check(mro));
+ n = PyTuple_GET_SIZE(mro);
+ for (i = 0; i < n; i++) {
+ base = PyTuple_GET_ITEM(mro, i);
+ if (PyClass_Check(base))
+ dict = ((PyClassObject *)base)->cl_dict;
+ else {
+ assert(PyType_Check(base));
+ dict = ((PyTypeObject *)base)->tp_dict;
+ }
+ assert(dict && PyDict_Check(dict));
+ res = PyDict_GetItem(dict, name);
+ if (res != NULL)
+ return base;
+ }
+ return NULL;
+ }
+
+ else if (PyClass_Check(klass)) { // old style classes
+ // This code is borrowed/adapted from class_lookup in classobject.c
+ PyClassObject* cp = (PyClassObject*)klass;
+ PyObject *value = PyDict_GetItem(cp->cl_dict, name);
+ if (value != NULL) {
+ return (PyObject*)cp;
+ }
+ n = PyTuple_Size(cp->cl_bases);
+ for (i = 0; i < n; i++) {
+ PyObject* base = PyTuple_GetItem(cp->cl_bases, i);
+ PyObject *v = PyFindClassWithAttr(base, name);
+ if (v != NULL)
+ return v;
+ }
+ return NULL;
+ }
+ return NULL;
+}
+#endif
+
+
+static
+PyObject* PyMethod_GetDefiningClass(PyObject* method, PyObject* nameo)
+{
+ PyObject* mgc = PyMethod_GET_CLASS(method);
+
+#if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
+ return mgc;
+#else // 2.2 and after, the hard way...
+ return PyFindClassWithAttr(mgc, nameo);
+#endif
+}
+
+
+
+// To avoid recursion when an overridden virtual method wants to call the base
+// class version, temporarily set an attribute in the instance with the same
+// name as the method. Then the PyObject_GetAttr in the next findCallback
+// will return this attribute and the PyMethod_Check will fail.
+
+void wxPyCallbackHelper::setRecursionGuard(PyObject* method) const
+{
+ PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
+ PyObject_SetAttr(m_self, func->func_name, Py_None);
+}
+
+void wxPyCallbackHelper::clearRecursionGuard(PyObject* method) const
+{
+ PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
+ if (PyObject_HasAttr(m_self, func->func_name)) {
+ PyObject_DelAttr(m_self, func->func_name);
+ }
+}
+
+// bool wxPyCallbackHelper::hasRecursionGuard(PyObject* method) const
+// {
+// PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
+// if (PyObject_HasAttr(m_self, func->func_name)) {
+// PyObject* attr = PyObject_GetAttr(m_self, func->func_name);
+// bool retval = (attr == Py_None);
+// Py_DECREF(attr);
+// return retval;
+// }
+// return false;
+// }
+
+
+bool wxPyCallbackHelper::findCallback(const char* name, bool setGuard) const {
+ wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
+ PyObject *method, *klass;
+ PyObject* nameo = PyString_FromString(name);
+ self->m_lastFound = NULL;
+
+ // If the object (m_self) has an attibute of the given name...
+ if (m_self && PyObject_HasAttr(m_self, nameo)) {
+ method = PyObject_GetAttr(m_self, nameo);
+
+ // ...and if that attribute is a method, and if that method's class is
+ // not from the registered class or a base class...
+ if (PyMethod_Check(method) &&
+ (klass = PyMethod_GetDefiningClass(method, nameo)) != NULL &&
+ (klass != m_class) &&
+ PyObject_IsSubclass(klass, m_class)) {
+
+ // ...then we'll save a pointer to the method so callCallback can
+ // call it. But first, set a recursion guard in case the
+ // overridden method wants to call the base class version.
+ if (setGuard)
+ setRecursionGuard(method);
+ self->m_lastFound = method;
+ }
+ else {
+ Py_DECREF(method);
+ }
+ }
+
+ Py_DECREF(nameo);
+ return m_lastFound != NULL;
+}
+
+
+int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
+ PyObject* result;
+ int retval = false;
+
+ result = callCallbackObj(argTuple);
+ if (result) { // Assumes an integer return type...
+ retval = PyInt_AsLong(result);
+ Py_DECREF(result);
+ PyErr_Clear(); // forget about it if it's not...
+ }
+ return retval;
+}
+
+// Invoke the Python callable object, returning the raw PyObject return
+// value. Caller should DECREF the return value and also manage the GIL.
+PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
+ PyObject* result;
+
+ // Save a copy of the pointer in case the callback generates another
+ // callback. In that case m_lastFound will have a different value when
+ // it gets back here...
+ PyObject* method = m_lastFound;
+
+ result = PyEval_CallObject(method, argTuple);
+ clearRecursionGuard(method);
+
+ Py_DECREF(argTuple);
+ Py_DECREF(method);
+ if (!result) {
+ PyErr_Print();
+ }
+ return result;
+}
+
+
+void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
+ cbh.setSelf(self, klass, incref);
+}
+
+bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name, bool setGuard) {
+ return cbh.findCallback(name, setGuard);
+}
+
+int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
+ return cbh.callCallback(argTuple);
+}
+
+PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
+ return cbh.callCallbackObj(argTuple);
+}
+
+
+void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
+ if (cbh->m_incRef && Py_IsInitialized()) {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ Py_XDECREF(cbh->m_self);
+ Py_XDECREF(cbh->m_class);
+ wxPyEndBlockThreads(blocked);
+ }
+}
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+// These event classes can be derived from in Python and passed through the event
+// system without losing anything. They do this by keeping a reference to
+// themselves and some special case handling in wxPyCallback::EventThunker.
+
+
+wxPyEvtSelfRef::wxPyEvtSelfRef() {
+ //m_self = Py_None; // **** We don't do normal ref counting to prevent
+ //Py_INCREF(m_self); // circular loops...
+ m_cloned = false;
+}
+
+wxPyEvtSelfRef::~wxPyEvtSelfRef() {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ if (m_cloned)
+ Py_DECREF(m_self);
+ wxPyEndBlockThreads(blocked);
+}
+
+void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ if (m_cloned)
+ Py_DECREF(m_self);
+ m_self = self;
+ if (clone) {
+ Py_INCREF(m_self);
+ m_cloned = true;
+ }
+ wxPyEndBlockThreads(blocked);
+}
+
+PyObject* wxPyEvtSelfRef::GetSelf() const {
+ Py_INCREF(m_self);
+ return m_self;
+}
+
+
+IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
+IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
+
+
+wxPyEvent::wxPyEvent(int winid, wxEventType commandType)
+ : wxEvent(winid, commandType) {
+}
+
+
+wxPyEvent::wxPyEvent(const wxPyEvent& evt)
+ : wxEvent(evt)
+{
+ SetSelf(evt.m_self, true);
+}
+
+
+wxPyEvent::~wxPyEvent() {
+}
+
+
+wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
+ : wxCommandEvent(commandType, id) {
+}
+
+
+wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
+ : wxCommandEvent(evt)
+{
+ SetSelf(evt.m_self, true);
+}
+
+
+wxPyCommandEvent::~wxPyCommandEvent() {
+}
+
+
+
+
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+// Convert a wxList to a Python List, only works for lists of wxObjects
+
+PyObject* wxPy_ConvertList(wxListBase* listbase) {
+ wxList* list = (wxList*)listbase; // this is probably bad...
+ PyObject* pyList;
+ PyObject* pyObj;
+ wxObject* wxObj;
+ wxNode* node = list->GetFirst();
+
+ wxPyBlock_t blocked = wxPyBeginBlockThreads();
+ pyList = PyList_New(0);
+ while (node) {
+ wxObj = node->GetData();
+ pyObj = wxPyMake_wxObject(wxObj,false);
+ PyList_Append(pyList, pyObj);
+ Py_DECREF(pyObj); // the Append also does an INCREF, that's one more than we need.
+ node = node->GetNext();
+ }
+ wxPyEndBlockThreads(blocked);
+ return pyList;
+}
+
+//----------------------------------------------------------------------
+
+long wxPyGetWinHandle(wxWindow* win) {
+
+#ifdef __WXMSW__
+ return (long)win->GetHandle();
+#endif
+
+#if defined(__WXGTK__) || defined(__WXX11)
+ return (long)GetXWindow(win);
+#endif
+
+#ifdef __WXMAC__
+ //return (long)MAC_WXHWND(win->MacGetTopLevelWindowRef());
+ return (long)win->GetHandle();
+#endif
+
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// Some helper functions for typemaps in my_typemaps.i, so they won't be
+// included in every file over and over again...
+
+wxString* wxString_in_helper(PyObject* source) {
+ wxString* target = NULL;
+
+ if (!PyString_Check(source) && !PyUnicode_Check(source)) {
+ PyErr_SetString(PyExc_TypeError, "String or Unicode type required");
+ return NULL;
+ }
+#if wxUSE_UNICODE
+ PyObject* uni = source;
+ if (PyString_Check(source)) {
+ uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict");
+ if (PyErr_Occurred()) return NULL;
+ }
+ target = new wxString();
+ size_t len = PyUnicode_GET_SIZE(uni);
+ if (len) {
+ PyUnicode_AsWideChar((PyUnicodeObject*)uni, target->GetWriteBuf(len), len);
+ target->UngetWriteBuf(len);
+ }
+
+ if (PyString_Check(source))
+ Py_DECREF(uni);
+#else
+ // Convert to a string object if it isn't already, then to wxString
+ PyObject* str = source;
+ if (PyUnicode_Check(source)) {
+ str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict");
+ if (PyErr_Occurred()) return NULL;
+ }
+ else if (!PyString_Check(source)) {
+ str = PyObject_Str(source);
+ if (PyErr_Occurred()) return NULL;
+ }
+ char* tmpPtr; Py_ssize_t tmpSize;
+ PyString_AsStringAndSize(str, &tmpPtr, &tmpSize);
+ target = new wxString(tmpPtr, tmpSize);
+
+ if (!PyString_Check(source))
+ Py_DECREF(str);
+#endif // wxUSE_UNICODE
+
+ return target;
+}
+
+
+// Similar to above except doesn't use "new" and doesn't set an exception
+wxString Py2wxString(PyObject* source)
+{
+ wxString target;
+
+#if wxUSE_UNICODE
+ // Convert to a unicode object, if not already, then to a wxString
+ PyObject* uni = source;
+ if (!PyUnicode_Check(source)) {
+ uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict");
+ if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
+ }
+ size_t len = PyUnicode_GET_SIZE(uni);
+ if (len) {
+ PyUnicode_AsWideChar((PyUnicodeObject*)uni, target.GetWriteBuf(len), len);
+ target.UngetWriteBuf();
+ }
+
+ if (!PyUnicode_Check(source))
+ Py_DECREF(uni);
+#else
+ // Convert to a string object if it isn't already, then to wxString
+ PyObject* str = source;
+ if (PyUnicode_Check(source)) {
+ str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict");
+ if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
+ }
+ else if (!PyString_Check(source)) {
+ str = PyObject_Str(source);
+ if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
+ }
+ char* tmpPtr; Py_ssize_t tmpSize;
+ PyString_AsStringAndSize(str, &tmpPtr, &tmpSize);
+ target = wxString(tmpPtr, tmpSize);
+
+ if (!PyString_Check(source))
+ Py_DECREF(str);
+#endif // wxUSE_UNICODE
+
+ return target;
+}
+
+
+// Make either a Python String or Unicode object, depending on build mode
+PyObject* wx2PyString(const wxString& src)
+{
+ PyObject* str;
+#if wxUSE_UNICODE
+ str = PyUnicode_FromWideChar(src.c_str(), src.Len());
+#else
+ str = PyString_FromStringAndSize(src.c_str(), src.Len());
+#endif
+ return str;
+}
+
+
+
+void wxSetDefaultPyEncoding(const char* encoding)
+{
+ strncpy(wxPyDefaultEncoding, encoding, DEFAULTENCODING_SIZE);
+}
+
+const char* wxGetDefaultPyEncoding()
+{
+ return wxPyDefaultEncoding;
+}
+
+//----------------------------------------------------------------------
+
+
+byte* byte_LIST_helper(PyObject* source) {
+ if (!PyList_Check(source)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list object.");
+ return NULL;
+ }
+ int count = PyList_Size(source);
+ byte* temp = new byte[count];
+ if (! temp) {
+ PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
+ return NULL;
+ }
+ for (int x=0; x<count; x++) {
+ PyObject* o = PyList_GetItem(source, x);
+ if (! PyInt_Check(o)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
+ return NULL;
+ }
+ temp[x] = (byte)PyInt_AsLong(o);
+ }
+ return temp;
+}
+
+
+int* int_LIST_helper(PyObject* source) {
+ if (!PyList_Check(source)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list object.");
+ return NULL;
+ }
+ int count = PyList_Size(source);
+ int* temp = new int[count];
+ if (! temp) {
+ PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
+ return NULL;
+ }
+ for (int x=0; x<count; x++) {
+ PyObject* o = PyList_GetItem(source, x);
+ if (! PyInt_Check(o)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
+ return NULL;
+ }
+ temp[x] = PyInt_AsLong(o);
+ }
+ return temp;
+}
+
+
+long* long_LIST_helper(PyObject* source) {
+ if (!PyList_Check(source)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list object.");
+ return NULL;
+ }
+ int count = PyList_Size(source);
+ long* temp = new long[count];
+ if (! temp) {
+ PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
+ return NULL;
+ }
+ for (int x=0; x<count; x++) {
+ PyObject* o = PyList_GetItem(source, x);
+ if (! PyInt_Check(o)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
+ return NULL;
+ }
+ temp[x] = PyInt_AsLong(o);
+ }
+ return temp;
+}
+
+
+char** string_LIST_helper(PyObject* source) {
+ if (!PyList_Check(source)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a list object.");
+ return NULL;
+ }
+ int count = PyList_Size(source);
+ char** temp = new char*[count];
+ if (! temp) {
+ PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
+ return NULL;