You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sip4-tqt/siplib/siplib.c

10502 lines
268 KiB

/*
* SIP library code.
*
* Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
*
* This file is part of SIP.
*
* This copy of SIP is licensed for use under the terms of the SIP License
* Agreement. See the file LICENSE for more details.
*
* This copy of SIP may also used under the terms of the GNU General Public
* License v2 or v3 as published by the Free Software Foundation which can be
* found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
*
* SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <Python.h>
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include "sip.h"
#include "sipint.h"
/* There doesn't seem to be a standard way of checking for C99 support. */
#if !defined(va_copy)
#define va_copy(d, s) ((d) = (s))
#endif
/*
* The Python metatype for a C++ wrapper type. We inherit everything from the
* standard Python metatype except the init and getattro methods and the size
* of the type object created is increased to accomodate the extra information
* we associate with a wrapped type.
*/
static PyObject *sipWrapperType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems);
static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name);
static int sipWrapperType_init(sipWrapperType *self, PyObject *args,
PyObject *kwds);
static int sipWrapperType_setattro(PyObject *self, PyObject *name,
PyObject *value);
static PyTypeObject sipWrapperType_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"sip.wrappertype", /* tp_name */
sizeof (sipWrapperType), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved (Python v3), tp_compare (Python v2) */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
sipWrapperType_getattro, /* tp_getattro */
sipWrapperType_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)sipWrapperType_init, /* tp_init */
sipWrapperType_alloc, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
};
/*
* The Python type that is the super-type for all C++ wrapper types that
* support parent/child relationships.
*/
static int sipWrapper_clear(sipWrapper *self);
static void sipWrapper_dealloc(sipWrapper *self);
static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg);
static sipWrapperType sipWrapper_Type = {
#if !defined(STACKLESS)
{
#endif
{
PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0)
"sip.wrapper", /* tp_name */
sizeof (sipWrapper), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)sipWrapper_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved (Python v3), tp_compare (Python v2) */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)sipWrapper_traverse, /* tp_traverse */
(inquiry)sipWrapper_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
},
#if !defined(STACKLESS)
},
#endif
0,
0
};
static void sip_api_bad_catcher_result(PyObject *method);
static void sip_api_bad_length_for_slice(SIP_SSIZE_T seqlen,
SIP_SSIZE_T slicelen);
static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...);
static PyObject *sip_api_call_method(int *isErr, PyObject *method,
const char *fmt, ...);
static SIP_SSIZE_T sip_api_convert_from_sequence_index(SIP_SSIZE_T idx,
SIP_SSIZE_T len);
static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
int flags);
static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td,
PyObject *transferObj, int flags, int *statep, int *iserrp);
static void *sip_api_force_convert_to_type(PyObject *pyObj,
const sipTypeDef *td, PyObject *transferObj, int flags, int *statep,
int *iserrp);
static int sip_api_can_convert_to_enum(PyObject *pyObj, const sipTypeDef *td);
static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state);
static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td,
PyObject *transferObj);
static int sip_api_get_state(PyObject *transferObj);
static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td);
static sipWrapperType *sip_api_map_int_to_class(int typeInt,
const sipIntTypeClassMap *map, int maplen);
static sipWrapperType *sip_api_map_string_to_class(const char *typeString,
const sipStringTypeClassMap *map, int maplen);
static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res,
const char *fmt, ...);
static void sip_api_trace(unsigned mask,const char *fmt,...);
static void sip_api_transfer_back(PyObject *self);
static void sip_api_transfer_to(PyObject *self, PyObject *owner);
static int sip_api_export_module(sipExportedModuleDef *client,
unsigned api_major, unsigned api_minor, void *unused);
static int sip_api_init_module(sipExportedModuleDef *client,
PyObject *mod_dict);
static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs,
const char *fmt, ...);
static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs,
PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
const char *fmt, ...);
static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0,
PyObject *sipArg1, const char *fmt, ...);
static void sip_api_no_function(PyObject *parseErr, const char *func,
const char *doc);
static void sip_api_no_method(PyObject *parseErr, const char *scope,
const char *method, const char *doc);
static void sip_api_abstract_method(const char *classname, const char *method);
static void sip_api_bad_class(const char *classname);
static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw);
static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc,
sipSimpleWrapper *sipSelf, const char *cname, const char *mname);
static void sip_api_call_hook(const char *hookname);
static void sip_api_raise_unknown_exception(void);
static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr);
static int sip_api_add_type_instance(PyObject *dict, const char *name,
void *cppPtr, const sipTypeDef *td);
static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg);
static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg,
sipPySlotType st);
static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod,
sipPySlotType st, const sipTypeDef *td, PyObject *arg0,
PyObject *arg1);
static void sip_api_add_delayed_dtor(sipSimpleWrapper *w);
static unsigned long sip_api_long_as_unsigned_long(PyObject *o);
static int sip_api_export_symbol(const char *name, void *sym);
static void *sip_api_import_symbol(const char *name);
static const sipTypeDef *sip_api_find_type(const char *type);
static sipWrapperType *sip_api_find_class(const char *type);
static const sipMappedType *sip_api_find_mapped_type(const char *type);
static PyTypeObject *sip_api_find_named_enum(const char *type);
static char sip_api_bytes_as_char(PyObject *obj);
static const char *sip_api_bytes_as_string(PyObject *obj);
static char sip_api_string_as_ascii_char(PyObject *obj);
static const char *sip_api_string_as_ascii_string(PyObject **obj);
static char sip_api_string_as_latin1_char(PyObject *obj);
static const char *sip_api_string_as_latin1_string(PyObject **obj);
static char sip_api_string_as_utf8_char(PyObject *obj);
static const char *sip_api_string_as_utf8_string(PyObject **obj);
#if defined(HAVE_WCHAR_H)
static wchar_t sip_api_unicode_as_wchar(PyObject *obj);
static wchar_t *sip_api_unicode_as_wstring(PyObject *obj);
#else
static int sip_api_unicode_as_wchar(PyObject *obj);
static int *sip_api_unicode_as_wstring(PyObject *obj);
#endif
static void sip_api_transfer_break(PyObject *self);
static int sip_api_deprecated(const char *classname, const char *method);
static int sip_api_register_py_type(PyTypeObject *supertype);
static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td);
static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type);
static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td);
static const char *sip_api_resolve_typedef(const char *name);
static int sip_api_register_attribute_getter(const sipTypeDef *td,
sipAttrGetterFunc getter);
static void sip_api_clear_any_slot_reference(sipSlot *slot);
static int sip_api_visit_slot(sipSlot *slot, visitproc visit, void *arg);
static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj);
static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp);
/*
* The data structure that represents the SIP API.
*/
static const sipAPIDef sip_api = {
/* This must be first. */
sip_api_export_module,
/*
* The following are part of the public API.
*/
(PyTypeObject *)&sipSimpleWrapper_Type,
(PyTypeObject *)&sipWrapper_Type,
&sipWrapperType_Type,
&sipVoidPtr_Type,
sip_api_bad_catcher_result,
sip_api_bad_length_for_slice,
sip_api_build_result,
sip_api_call_method,
sip_api_connect_rx,
sip_api_convert_from_sequence_index,
sip_api_can_convert_to_type,
sip_api_convert_to_type,
sip_api_force_convert_to_type,
sip_api_can_convert_to_enum,
sip_api_release_type,
sip_api_convert_from_type,
sip_api_convert_from_new_type,
sip_api_convert_from_enum,
sip_api_get_state,
sip_api_disconnect_rx,
sip_api_free,
sip_api_get_pyobject,
sip_api_malloc,
sip_api_parse_result,
sip_api_trace,
sip_api_transfer_back,
sip_api_transfer_to,
sip_api_transfer_break,
sip_api_long_as_unsigned_long,
sip_api_convert_from_void_ptr,
sip_api_convert_from_const_void_ptr,
sip_api_convert_from_void_ptr_and_size,
sip_api_convert_from_const_void_ptr_and_size,
sip_api_convert_to_void_ptr,
sip_api_export_symbol,
sip_api_import_symbol,
sip_api_find_type,
sip_api_register_py_type,
sip_api_type_from_py_type_object,
sip_api_type_scope,
sip_api_resolve_typedef,
sip_api_register_attribute_getter,
sip_api_is_api_enabled,
sip_api_bad_callable_arg,
/*
* The following are deprecated parts of the public API.
*/
sip_api_find_named_enum,
sip_api_find_mapped_type,
sip_api_find_class,
sip_api_map_int_to_class,
sip_api_map_string_to_class,
/*
* The following may be used by TQt support code but by no other handwritten
* code.
*/
sip_api_free_sipslot,
sip_api_same_slot,
sip_api_convert_rx,
sip_api_invoke_slot,
sip_api_save_slot,
sip_api_clear_any_slot_reference,
sip_api_visit_slot,
/*
* The following are not part of the public API.
*/
sip_api_init_module,
sip_api_parse_args,
sip_api_parse_pair,
sip_api_common_dtor,
sip_api_no_function,
sip_api_no_method,
sip_api_abstract_method,
sip_api_bad_class,
sip_api_get_cpp_ptr,
sip_api_get_complex_cpp_ptr,
sip_api_is_py_method,
sip_api_call_hook,
sip_api_start_thread,
sip_api_end_thread,
sip_api_raise_unknown_exception,
sip_api_raise_type_exception,
sip_api_add_type_instance,
sip_api_bad_operator_arg,
sip_api_pyslot_extend,
sip_api_add_delayed_dtor,
sip_api_bytes_as_char,
sip_api_bytes_as_string,
sip_api_string_as_ascii_char,
sip_api_string_as_ascii_string,
sip_api_string_as_latin1_char,
sip_api_string_as_latin1_string,
sip_api_string_as_utf8_char,
sip_api_string_as_utf8_string,
sip_api_unicode_as_wchar,
sip_api_unicode_as_wstring,
sip_api_deprecated,
sip_api_keep_reference,
sip_api_parse_kwd_args,
sip_api_add_exception
};
#define AUTO_DOCSTRING '\1' /* Marks an auto class docstring. */
/*
* These are the format flags supported by argument parsers.
*/
#define FMT_AP_DEREF 0x01 /* The pointer will be dereferenced. */
#define FMT_AP_TRANSFER 0x02 /* Implement /Transfer/. */
#define FMT_AP_TRANSFER_BACK 0x04 /* Implement /TransferBack/. */
#define FMT_AP_NO_CONVERTORS 0x08 /* Suppress any convertors. */
#define FMT_AP_TRANSFER_THIS 0x10 /* Support for /TransferThis/. */
/*
* These are the format flags supported by result parsers. Deprecated values
* have a _DEPR suffix.
*/
#define FMT_RP_DEREF 0x01 /* The pointer will be dereferenced. */
#define FMT_RP_FACTORY 0x02 /* /Factory/ or /TransferBack/. */
#define FMT_RP_MAKE_COPY 0x04 /* Return a copy of the value. */
#define FMT_RP_NO_STATE_DEPR 0x04 /* Don't return the C/C++ state. */
/*
* The different reasons for failing to parse an overload. These include
* internal (i.e. non-user) errors.
*/
typedef enum {
Ok, Unbound, TooFew, TooMany, UnknownKeyword, Duplicate, WrongType, Raised,
KeywordNotString, Exception
} sipParseFailureReason;
/*
* The description of a failure to parse an overload because of a user error.
*/
typedef struct _sipParseFailure {
sipParseFailureReason reason; /* The reason for the failure. */
const char *detail_str; /* The detail if a string. */
PyObject *detail_obj; /* The detail if a Python object. */
int arg_nr; /* The wrong positional argument. */
const char *arg_name; /* The wrong keyword argument. */
} sipParseFailure;
/*
* An entry in a linked list of name/symbol pairs.
*/
typedef struct _sipSymbol {
const char *name; /* The name. */
void *symbol; /* The symbol. */
struct _sipSymbol *next; /* The next in the list. */
} sipSymbol;
/*
* An entry in a linked list of Python objects.
*/
typedef struct _sipPyObject {
PyObject *object; /* The Python object. */
struct _sipPyObject *next; /* The next in the list. */
} sipPyObject;
/*
* An entry in the linked list of attribute getters.
*/
typedef struct _sipAttrGetter {
PyTypeObject *type; /* The Python type being handled. */
sipAttrGetterFunc getter; /* The getter. */
struct _sipAttrGetter *next; /* The next in the list. */
} sipAttrGetter;
/*****************************************************************************
* The structures to support a Python type to hold a named enum.
*****************************************************************************/
static PyObject *sipEnumType_alloc(PyTypeObject *self, SIP_SSIZE_T nitems);
/*
* The type data structure. We inherit everything from the standard Python
* metatype and the size of the type object created is increased to accomodate
* the extra information we associate with a named enum type.
*/
static PyTypeObject sipEnumType_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"sip.enumtype", /* tp_name */
sizeof (sipEnumTypeObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved (Python v3), tp_compare (Python v2) */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
sipEnumType_alloc, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
};
sipTQtAPI *sipTQtSupport = NULL;
sipTypeDef *sipTQObjectType;
/*
* Various strings as Python objects created as and when needed.
*/
static PyObject *licenseName = NULL;
static PyObject *licenseeName = NULL;
static PyObject *typeName = NULL;
static PyObject *timestampName = NULL;
static PyObject *signatureName = NULL;
static sipObjectMap cppPyMap; /* The C/C++ to Python map. */
static sipExportedModuleDef *moduleList = NULL; /* List of registered modules. */
static unsigned traceMask = 0; /* The current trace mask. */
static sipTypeDef *currentType = NULL; /* The type being created. */
static PyObject *type_unpickler; /* The type unpickler function. */
static PyObject *enum_unpickler; /* The enum unpickler function. */
static sipSymbol *sipSymbolList = NULL; /* The list of published symbols. */
static sipAttrGetter *sipAttrGetters = NULL; /* The list of attribute getters. */
static sipPyObject *sipRegisteredPyTypes = NULL; /* Registered Python types. */
static PyInterpreterState *sipInterpreter = NULL; /* The interpreter. */
static void addClassSlots(sipWrapperType *wt, sipClassTypeDef *ctd);
static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots);
static void *findSlot(PyObject *self, sipPySlotType st);
static void *findSlotInType(sipPySlotDef *psd, sipPySlotType st);
static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2,
sipPySlotType st);
static int ssizeobjargprocSlot(PyObject *self, SIP_SSIZE_T arg1,
PyObject *arg2, sipPySlotType st);
static PyObject *buildObject(PyObject *tup, const char *fmt, va_list va);
static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs,
PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
const char *fmt, va_list va_orig);
static int parsePass1(PyObject **parseErrp, sipSimpleWrapper **selfp,
int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs,
const char **kwdlist, PyObject **unused, const char *fmt, va_list va);
static int parsePass2(sipSimpleWrapper *self, int selfarg, PyObject *sipArgs,
PyObject *sipKwdArgs, const char **kwdlist, const char *fmt,
va_list va);
static PyObject *signature_FromDocstring(const char *doc, SIP_SSIZE_T line);
static PyObject *detail_FromFailure(PyObject *failure_obj);
static int isTQObject(PyObject *obj);
static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td);
static int convertFromSequence(PyObject *seq, const sipTypeDef *td,
void **array, SIP_SSIZE_T *nr_elem);
static PyObject *convertToSequence(void *array, SIP_SSIZE_T nr_elem,
const sipTypeDef *td);
static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr,
sipSimpleWrapper **selfp);
static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm);
static int compareTypedefName(const void *key, const void *el);
static int checkPointer(void *ptr);
static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type,
const sipTypeDef *dst_type);
static void finalise(void);
static PyObject *getDefaultBases(void);
static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict,
sipExportedModuleDef *client);
static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td,
PyObject *bases, PyObject *metatype, PyObject *mod_dict,
sipExportedModuleDef *client);
static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd,
PyObject *mod_dict);
static int createMappedType(sipExportedModuleDef *client,
sipMappedTypeDef *mtd, PyObject *mod_dict);
static sipExportedModuleDef *getModule(PyObject *mname_obj);
static PyObject *pickle_type(PyObject *obj, PyObject *);
static PyObject *unpickle_type(PyObject *, PyObject *args);
static PyObject *pickle_enum(PyObject *obj, PyObject *);
static PyObject *unpickle_enum(PyObject *, PyObject *args);
static int setReduce(PyTypeObject *type, PyMethodDef *pickler);
static int createEnumType(sipExportedModuleDef *client, sipEnumTypeDef *etd,
PyObject *mod_dict);
static PyObject *createTypeDict(PyObject *mname);
static sipExportedModuleDef *getTypeModule(const sipEncodedTypeDef *enc,
sipExportedModuleDef *em);
static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc,
sipExportedModuleDef *em);
static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr);
static void *getPtrTypeDef(sipSimpleWrapper *self,
const sipClassTypeDef **ctd);
static int addInstances(PyObject *dict, sipInstancesDef *id);
static int addVoidPtrInstances(PyObject *dict, sipVoidPtrInstanceDef *vi);
static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci);
static int addStringInstances(PyObject *dict, sipStringInstanceDef *si);
static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii);
static int addLongInstances(PyObject *dict, sipLongInstanceDef *li);
static int addUnsignedLongInstances(PyObject *dict,
sipUnsignedLongInstanceDef *uli);
static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli);
static int addUnsignedLongLongInstances(PyObject *dict,
sipUnsignedLongLongInstanceDef *ulli);
static int addDoubleInstances(PyObject *dict, sipDoubleInstanceDef *di);
static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti);
static int addSingleTypeInstance(PyObject *dict, const char *name,
void *cppPtr, const sipTypeDef *td, int initflags);
static int addLicense(PyObject *dict, sipLicenseDef *lc);
static PyObject *cast(PyObject *self, PyObject *args);
static PyObject *callDtor(PyObject *self, PyObject *args);
static PyObject *dumpWrapper(PyObject *self, PyObject *args);
static PyObject *isDeleted(PyObject *self, PyObject *args);
static PyObject *isPyOwned(PyObject *self, PyObject *args);
static PyObject *setDeleted(PyObject *self, PyObject *args);
static PyObject *setTraceMask(PyObject *self, PyObject *args);
static PyObject *wrapInstance(PyObject *self, PyObject *args);
static PyObject *unwrapInstance(PyObject *self, PyObject *args);
static PyObject *transferBack(PyObject *self, PyObject *args);
static PyObject *transferTo(PyObject *self, PyObject *args);
static void print_object(const char *label, PyObject *obj);
static void addToParent(sipWrapper *self, sipWrapper *owner);
static void removeFromParent(sipWrapper *self);
static void release(void *addr, const sipTypeDef *td, int state);
static void callPyDtor(sipSimpleWrapper *self);
static int parseBytes_AsCharArray(PyObject *obj, const char **ap,
SIP_SSIZE_T *aszp);
static int parseBytes_AsChar(PyObject *obj, char *ap);
static int parseBytes_AsString(PyObject *obj, const char **ap);
static int parseString_AsASCIIChar(PyObject *obj, char *ap);
static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap);
static int parseString_AsLatin1Char(PyObject *obj, char *ap);
static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap);
static int parseString_AsUTF8Char(PyObject *obj, char *ap);
static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap);
static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap);
static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj,
const char **ap);
#if defined(HAVE_WCHAR_H)
static int parseWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp);
static int convertToWCharArray(PyObject *obj, wchar_t **ap, SIP_SSIZE_T *aszp);
static int parseWChar(PyObject *obj, wchar_t *ap);
static int convertToWChar(PyObject *obj, wchar_t *ap);
static int parseWCharString(PyObject *obj, wchar_t **ap);
static int convertToWCharString(PyObject *obj, wchar_t **ap);
#else
static void raiseNoWChar();
#endif
static void *getComplexCppPtr(sipSimpleWrapper *w, const sipTypeDef *td);
static PyObject *findPyType(const char *name);
static int addPyObjectToList(sipPyObject **head, PyObject *object);
static PyObject *getDictFromObject(PyObject *obj);
static void forgetObject(sipSimpleWrapper *sw);
static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod,
PyObject *dict);
static int add_lazy_attrs(sipTypeDef *td);
static int add_all_lazy_attrs(sipTypeDef *td);
static int objectify(const char *s, PyObject **objp);
static void add_failure(PyObject **parseErrp, sipParseFailure *failure);
static PyObject *bad_type_str(int arg_nr, PyObject *arg);
/*
* The Python module initialisation function.
*/
#if PY_MAJOR_VERSION >= 3
#define SIP_MODULE_ENTRY PyInit_sip
#define SIP_MODULE_TYPE PyObject *
#define SIP_MODULE_DISCARD(m) Py_DECREF(m)
#define SIP_FATAL(s) return NULL
#define SIP_MODULE_RETURN(m) return (m)
#else
#define SIP_MODULE_ENTRY initsip
#define SIP_MODULE_TYPE void
#define SIP_MODULE_DISCARD(m)
#define SIP_FATAL(s) Py_FatalError(s)
#define SIP_MODULE_RETURN(m)
#endif
#if defined(SIP_STATIC_MODULE)
SIP_MODULE_TYPE SIP_MODULE_ENTRY(void)
#else
PyMODINIT_FUNC SIP_MODULE_ENTRY(void)
#endif
{
static PyMethodDef methods[] = {
{"cast", cast, METH_VARARGS, NULL},
{"delete", callDtor, METH_VARARGS, NULL},
{"dump", dumpWrapper, METH_VARARGS, NULL},
{"getapi", sipGetAPI, METH_VARARGS, NULL},
{"isdeleted", isDeleted, METH_VARARGS, NULL},
{"ispyowned", isPyOwned, METH_VARARGS, NULL},
{"setapi", sipSetAPI, METH_VARARGS, NULL},
{"setdeleted", setDeleted, METH_VARARGS, NULL},
{"settracemask", setTraceMask, METH_VARARGS, NULL},
{"transferback", transferBack, METH_VARARGS, NULL},
{"transferto", transferTo, METH_VARARGS, NULL},
{"wrapinstance", wrapInstance, METH_VARARGS, NULL},
{"unwrapinstance", unwrapInstance, METH_VARARGS, NULL},
{"_unpickle_type", unpickle_type, METH_VARARGS, NULL},
{"_unpickle_enum", unpickle_enum, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
#if PY_MAJOR_VERSION >= 3
static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"sip", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#endif
int rc;
PyObject *mod, *mod_dict, *obj;
#ifdef WITH_THREAD
PyEval_InitThreads();
#endif
/* Initialise the types. */
sipWrapperType_Type.tp_base = &PyType_Type;
if (PyType_Ready(&sipWrapperType_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.wrappertype type");
if (PyType_Ready((PyTypeObject *)&sipSimpleWrapper_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.simplewrapper type");
if (sip_api_register_py_type((PyTypeObject *)&sipSimpleWrapper_Type) < 0)
SIP_FATAL("sip: Failed to register sip.simplewrapper type");
#if defined(STACKLESS)
sipWrapper_Type.super.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
#elif PY_VERSION_HEX >= 0x02050000
sipWrapper_Type.super.ht_type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
#else
sipWrapper_Type.super.type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type;
#endif
if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.wrapper type");
if (PyType_Ready(&sipMethodDescr_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.methoddescriptor type");
if (PyType_Ready(&sipVariableDescr_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.variabledescriptor type");
sipEnumType_Type.tp_base = &PyType_Type;
if (PyType_Ready(&sipEnumType_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.enumtype type");
if (PyType_Ready(&sipVoidPtr_Type) < 0)
SIP_FATAL("sip: Failed to initialise sip.voidptr type");
#if PY_MAJOR_VERSION >= 3
mod = PyModule_Create(&module_def);
#else
mod = Py_InitModule("sip", methods);
#endif
if (mod == NULL)
SIP_FATAL("sip: Failed to intialise sip module");
mod_dict = PyModule_GetDict(mod);
/* Get a reference to the pickle helpers. */
type_unpickler = PyDict_GetItemString(mod_dict, "_unpickle_type");
enum_unpickler = PyDict_GetItemString(mod_dict, "_unpickle_enum");
if (type_unpickler == NULL || enum_unpickler == NULL)
{
SIP_MODULE_DISCARD(mod);
SIP_FATAL("sip: Failed to get pickle helpers");
}
/* Publish the SIP API. */
#if defined(SIP_USE_PYCAPSULE)
obj = PyCapsule_New((void *)&sip_api, "sip._C_API", NULL);
#else
obj = PyCObject_FromVoidPtr((void *)&sip_api, NULL);
#endif
if (obj == NULL)
{
SIP_MODULE_DISCARD(mod);
SIP_FATAL("sip: Failed to create _C_API object");
}
rc = PyDict_SetItemString(mod_dict, "_C_API", obj);
Py_DECREF(obj);
if (rc < 0)
{
SIP_MODULE_DISCARD(mod);
SIP_FATAL("sip: Failed to add _C_API object to module dictionary");
}
/* Add the SIP version number, but don't worry about errors. */
#if PY_MAJOR_VERSION >= 3
obj = PyLong_FromLong(SIP_VERSION);
#else
obj = PyInt_FromLong(SIP_VERSION);
#endif
if (obj != NULL)
{
PyDict_SetItemString(mod_dict, "SIP_VERSION", obj);
Py_DECREF(obj);
}
#if PY_MAJOR_VERSION >= 3
obj = PyUnicode_FromString(SIP_VERSION_STR);
#else
obj = PyString_FromString(SIP_VERSION_STR);
#endif
if (obj != NULL)
{
PyDict_SetItemString(mod_dict, "SIP_VERSION_STR", obj);
Py_DECREF(obj);
}
/* Add the type objects, but don't worry about errors. */
PyDict_SetItemString(mod_dict, "wrappertype",
(PyObject *)&sipWrapperType_Type);
PyDict_SetItemString(mod_dict, "simplewrapper",
(PyObject *)&sipSimpleWrapper_Type);
PyDict_SetItemString(mod_dict, "wrapper", (PyObject *)&sipWrapper_Type);
PyDict_SetItemString(mod_dict, "voidptr", (PyObject *)&sipVoidPtr_Type);
/* Initialise the module if it hasn't already been done. */
if (sipInterpreter == NULL)
{
Py_AtExit(finalise);
/* Initialise the object map. */
sipOMInit(&cppPyMap);
sipTQtSupport = NULL;
/*
* Get the current interpreter. This will be shared between all
* threads.
*/
sipInterpreter = PyThreadState_Get()->interp;
}
SIP_MODULE_RETURN(mod);
}
/*
* Display a printf() style message to stderr according to the current trace
* mask.
*/
static void sip_api_trace(unsigned mask, const char *fmt, ...)
{
va_list ap;
va_start(ap,fmt);
if (mask & traceMask)
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/*
* Set the trace mask.
*/
static PyObject *setTraceMask(PyObject *self, PyObject *args)
{
unsigned new_mask;
if (PyArg_ParseTuple(args, "I:settracemask", &new_mask))
{
traceMask = new_mask;
Py_INCREF(Py_None);
return Py_None;
}
return NULL;
}
/*
* Dump various bits of potentially useful information to stdout.
*/
static PyObject *dumpWrapper(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
if (PyArg_ParseTuple(args, "O!:dump", &sipSimpleWrapper_Type, &sw))
{
print_object(NULL, (PyObject *)sw);
#if PY_VERSION_HEX >= 0x02050000
printf(" Reference count: %" PY_FORMAT_SIZE_T "d\n", Py_REFCNT(sw));
#else
printf(" Reference count: %d\n", Py_REFCNT(sw));
#endif
printf(" Address of wrapped object: %p\n", sipGetAddress(sw));
printf(" To be destroyed by: %s\n", (sipIsPyOwned(sw) ? "Python" : "C/C++"));
printf(" Derived class?: %s\n", (sipIsDerived(sw) ? "yes" : "no"));
if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
{
sipWrapper *w = (sipWrapper *)sw;
print_object("Parent wrapper", (PyObject *)w->parent);
print_object("Next sibling wrapper", (PyObject *)w->sibling_next);
print_object("Previous sibling wrapper",
(PyObject *)w->sibling_prev);
print_object("First child wrapper", (PyObject *)w->first_child);
}
Py_INCREF(Py_None);
return Py_None;
}
return NULL;
}
/*
* Write a reference to a wrapper to stdout.
*/
static void print_object(const char *label, PyObject *obj)
{
if (label != NULL)
printf(" %s: ", label);
if (obj != NULL)
PyObject_Print(obj, stdout, 0);
else
printf("NULL");
printf("\n");
}
/*
* Transfer the ownership of an instance to C/C++.
*/
static PyObject *transferTo(PyObject *self, PyObject *args)
{
PyObject *w, *owner;
if (PyArg_ParseTuple(args, "O!O:transferto", &sipWrapper_Type, &w, &owner))
{
if (owner == Py_None)
owner = NULL;
else if (PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type))
{
PyErr_Format(PyExc_TypeError, "transferto() argument 2 must be sip.wrapper, not %s", Py_TYPE(owner)->tp_name);
return NULL;
}
sip_api_transfer_to(w, owner);
Py_INCREF(Py_None);
return Py_None;
}
return NULL;
}
/*
* Transfer the ownership of an instance to Python.
*/
static PyObject *transferBack(PyObject *self, PyObject *args)
{
PyObject *w;
if (PyArg_ParseTuple(args, "O!:transferback", &sipWrapper_Type, &w))
{
sip_api_transfer_back(w);
Py_INCREF(Py_None);
return Py_None;
}
return NULL;
}
/*
* Cast an instance to one of it's sub or super-classes by returning a new
* Python object with the superclass type wrapping the same C++ instance.
*/
static PyObject *cast(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
sipWrapperType *wt;
const sipTypeDef *td;
void *addr;
PyTypeObject *ft, *tt;
if (!PyArg_ParseTuple(args, "O!O!:cast", &sipSimpleWrapper_Type, &sw, &sipWrapperType_Type, &wt))
return NULL;
ft = Py_TYPE(sw);
tt = (PyTypeObject *)wt;
if (ft == tt || PyType_IsSubtype(tt, ft))
td = NULL;
else if (PyType_IsSubtype(ft, tt))
td = wt->type;
else
{
PyErr_SetString(PyExc_TypeError, "argument 1 of sip.cast() must be an instance of a sub or super-type of argument 2");
return NULL;
}
if ((addr = sip_api_get_cpp_ptr(sw, td)) == NULL)
return NULL;
/*
* We don't put this new object into the map so that the original object is
* always found. It would also totally confuse the map logic.
*/
return sipWrapSimpleInstance(addr, wt->type, NULL, (sw->flags | SIP_NOT_IN_MAP) & ~SIP_PY_OWNED);
}
/*
* Call an instance's dtor.
*/
static PyObject *callDtor(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
void *addr;
const sipClassTypeDef *ctd;
if (!PyArg_ParseTuple(args, "O!:delete", &sipSimpleWrapper_Type, &sw))
return NULL;
addr = getPtrTypeDef(sw, &ctd);
if (checkPointer(addr) < 0)
return NULL;
if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
{
/*
* Transfer ownership to C++ so we don't try to release it again when
* the Python object is garbage collected.
*/
removeFromParent((sipWrapper *)sw);
sipResetPyOwned(sw);
}
release(addr, (const sipTypeDef *)ctd, sw->flags);
Py_INCREF(Py_None);
return Py_None;
}
/*
* Check if an instance still exists without raising an exception.
*/
static PyObject *isDeleted(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
PyObject *res;
if (!PyArg_ParseTuple(args, "O!:isdeleted", &sipSimpleWrapper_Type, &sw))
return NULL;
res = (sipGetAddress(sw) == NULL ? Py_True : Py_False);
Py_INCREF(res);
return res;
}
/*
* Check if an instance is owned by Python or C/C++.
*/
static PyObject *isPyOwned(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
PyObject *res;
if (!PyArg_ParseTuple(args, "O!:ispyowned", &sipSimpleWrapper_Type, &sw))
return NULL;
res = (sipIsPyOwned(sw) ? Py_True : Py_False);
Py_INCREF(res);
return res;
}
/*
* Mark an instance as having been deleted.
*/
static PyObject *setDeleted(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
if (!PyArg_ParseTuple(args, "O!:setdeleted", &sipSimpleWrapper_Type, &sw))
return NULL;
if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type))
{
/*
* Transfer ownership to C++ so we don't try to release it when the
* Python object is garbage collected.
*/
removeFromParent((sipWrapper *)sw);
sipResetPyOwned(sw);
}
sw->u.cppPtr = NULL;
Py_INCREF(Py_None);
return Py_None;
}
/*
* Unwrap an instance.
*/
static PyObject *unwrapInstance(PyObject *self, PyObject *args)
{
sipSimpleWrapper *sw;
if (PyArg_ParseTuple(args, "O!:unwrapinstance", &sipSimpleWrapper_Type, &sw))
{
void *addr;
/*
* We just get the pointer but don't try and cast it (which isn't
* needed and wouldn't work with the way casts are currently
* implemented if we are unwrapping something derived from a wrapped
* class).
*/
if ((addr = sip_api_get_cpp_ptr(sw, NULL)) == NULL)
return NULL;
return PyLong_FromVoidPtr(addr);
}
return NULL;
}
/*
* Wrap an instance.
*/
static PyObject *wrapInstance(PyObject *self, PyObject *args)
{
unsigned long addr;
sipWrapperType *wt;
if (PyArg_ParseTuple(args, "kO!:wrapinstance", &addr, &sipWrapperType_Type, &wt))
return sip_api_convert_from_type((void *)addr, wt->type, NULL);
return NULL;
}
/*
* Register a client module. A negative value is returned and an exception
* raised if there was an error.
*/
static int sip_api_export_module(sipExportedModuleDef *client,
unsigned api_major, unsigned api_minor, void *unused)
{
sipExportedModuleDef *em;
const char *full_name = sipNameOfModule(client);
/* Check that we can support it. */
if (api_major != SIP_API_MAJOR_NR || api_minor > SIP_API_MINOR_NR)
{
#if SIP_API_MINOR_NR > 0
PyErr_Format(PyExc_RuntimeError,
"the sip module implements API v%d.0 to v%d.%d but the %s module requires API v%d.%d",
SIP_API_MAJOR_NR, SIP_API_MAJOR_NR, SIP_API_MINOR_NR,
full_name, api_major, api_minor);
#else
PyErr_Format(PyExc_RuntimeError,
"the sip module implements API v%d.0 but the %s module requires API v%d.%d",
SIP_API_MAJOR_NR, full_name, api_major, api_minor);
#endif
return -1;
}
/* Import any required modules. */
if (client->em_imports != NULL)
{
sipImportedModuleDef *im = client->em_imports;
while (im->im_name != NULL)
{
PyObject *mod;
if ((mod = PyImport_ImportModule(im->im_name)) == NULL)
return -1;
for (em = moduleList; em != NULL; em = em->em_next)
if (strcmp(sipNameOfModule(em), im->im_name) == 0)
break;
if (em == NULL)
{
PyErr_Format(PyExc_RuntimeError,
"the %s module failed to register with the sip module",
im->im_name);
return -1;
}
/* Check the versions are compatible. */
if (im->im_version >= 0 || em->em_version >= 0)
if (im->im_version != em->em_version)
{
PyErr_Format(PyExc_RuntimeError,
"the %s module is version %d but the %s module requires version %d",
sipNameOfModule(em), em->em_version, full_name,
im->im_version);
return -1;
}
/* Save the imported module. */
im->im_module = em;
++im;
}
}
for (em = moduleList; em != NULL; em = em->em_next)
{
/* SIP clients must have unique names. */
if (strcmp(sipNameOfModule(em), full_name) == 0)
{
PyErr_Format(PyExc_RuntimeError,
"the sip module has already registered a module called %s",
full_name);
return -1;
}
/* Only one module can claim to wrap TQObject. */
if (em->em_qt_api != NULL && client->em_qt_api != NULL)
{
PyErr_Format(PyExc_RuntimeError,
"the %s and %s modules both wrap the TQObject class",
full_name, sipNameOfModule(em));
return -1;
}
}
/* Convert the module name to an object. */
#if PY_MAJOR_VERSION >= 3
client->em_nameobj = PyUnicode_FromString(full_name);
#else
client->em_nameobj = PyString_FromString(full_name);
#endif
if (client->em_nameobj == NULL)
return -1;
/* Add it to the list of client modules. */
client->em_next = moduleList;
moduleList = client;
return 0;
}
/*
* Initialise the contents of a client module. By this time anything that
* this depends on should have been initialised. A negative value is returned
* and an exception raised if there was an error.
*/
static int sip_api_init_module(sipExportedModuleDef *client,
PyObject *mod_dict)
{
sipExportedModuleDef *em;
sipEnumMemberDef *emd;
int i;
/* Handle any API. */
if (sipInitAPI(client, mod_dict) < 0)
return -1;
/* Create the module's types. */
for (i = 0; i < client->em_nrtypes; ++i)
{
sipTypeDef *td = client->em_types[i];
/* Skip external classes. */
if (td == NULL)
continue;
/* Skip if already initialised. */
if (td->td_module != NULL)
continue;
/* If it is a stub then just set the module so we can get its name. */
if (sipTypeIsStub(td))
{
td->td_module = client;
continue;
}
if (sipTypeIsEnum(td))
{
sipEnumTypeDef *etd = (sipEnumTypeDef *)td;
if (td->td_version < 0 || sipIsRangeEnabled(client, td->td_version))
if (createEnumType(client, etd, mod_dict) < 0)
return -1;
/*
* Register the enum pickler for scoped enums (unscoped, ie. those
* not nested, don't need special treatment).
*/
if (etd->etd_scope >= 0)
{
static PyMethodDef md = {
"_pickle_enum", pickle_enum, METH_NOARGS, NULL
};
if (setReduce(sipTypeAsPyTypeObject(td), &md) < 0)
return -1;
}
}
else if (sipTypeIsMapped(td))
{
sipMappedTypeDef *mtd = (sipMappedTypeDef *)td;
/* If there is a name then we need a namespace. */
if (mtd->mtd_container.cod_name >= 0)
{
if (createMappedType(client, mtd, mod_dict) < 0)
return -1;
}
else
{
td->td_module = client;
}
}
else
{
sipClassTypeDef *ctd = (sipClassTypeDef *)td;
/* See if this is a namespace extender. */
if (ctd->ctd_container.cod_name < 0)
{
sipTypeDef *real_nspace;
sipClassTypeDef **last;
ctd->ctd_base.td_module = client;
real_nspace = getGeneratedType(&ctd->ctd_container.cod_scope,
client);
/* Append this type to the real one. */
last = &((sipClassTypeDef *)real_nspace)->ctd_nsextender;
while (*last != NULL)
last = &(*last)->ctd_nsextender;
*last = ctd;
/*
* Save the real namespace type so that it is the correct scope
* for any enums or classes defined in this module.
*/
client->em_types[i] = real_nspace;
}
else if (createClassType(client, ctd, mod_dict) < 0)
return -1;
}
}
/* Set any TQt support API. */
if (client->em_qt_api != NULL)
{
sipTQtSupport = client->em_qt_api;
sipTQObjectType = *sipTQtSupport->qt_qobject;
}
/* Append any initialiser extenders to the relevant classes. */
if (client->em_initextend != NULL)
{
sipInitExtenderDef *ie = client->em_initextend;
while (ie->ie_extender != NULL)
{
sipTypeDef *td = getGeneratedType(&ie->ie_class, client);
int enabled;
if (ie->ie_api_range < 0)
enabled = TRUE;
else
enabled = sipIsRangeEnabled(td->td_module, ie->ie_api_range);
if (enabled)
{
sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td);
ie->ie_next = wt->iextend;
wt->iextend = ie;
}
++ie;
}
}
/* Set the base class object for any sub-class convertors. */
if (client->em_convertors != NULL)
{
sipSubClassConvertorDef *scc = client->em_convertors;
while (scc->scc_convertor != NULL)
{
scc->scc_basetype = getGeneratedType(&scc->scc_base, client);
++scc;
}
}
/* Create the module's enum members. */
for (emd = client->em_enummembers, i = 0; i < client->em_nrenummembers; ++i, ++emd)
{
PyObject *mo;
if ((mo = sip_api_convert_from_enum(emd->em_val, client->em_types[emd->em_enum])) == NULL)
return -1;
if (PyDict_SetItemString(mod_dict, emd->em_name, mo) < 0)
return -1;
Py_DECREF(mo);
}
/*
* Add any class static instances. We need to do this once all types are
* fully formed because of potential interdependencies.
*/
for (i = 0; i < client->em_nrtypes; ++i)
{
sipTypeDef *td = client->em_types[i];
if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
if (addInstances((sipTypeAsPyTypeObject(td))->tp_dict, &((sipClassTypeDef *)td)->ctd_container.cod_instances) < 0)
return -1;
}
/* Add any global static instances. */
if (addInstances(mod_dict, &client->em_instances) < 0)
return -1;
/* Add any license. */
if (client->em_license != NULL && addLicense(mod_dict, client->em_license) < 0)
return -1;
/* See if the new module satisfies any outstanding external types. */
for (em = moduleList; em != NULL; em = em->em_next)
{
sipExternalTypeDef *etd;
if (em == client || em->em_external == NULL)
continue;
for (etd = em->em_external; etd->et_nr >= 0; ++etd)
{
if (etd->et_name == NULL)
continue;
for (i = 0; i < client->em_nrtypes; ++i)
{
sipTypeDef *td = client->em_types[i];
if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td))
{
const char *pyname = sipPyNameOfContainer(
&((sipClassTypeDef *)td)->ctd_container, td);
if (strcmp(etd->et_name, pyname) == 0)
{
em->em_types[etd->et_nr] = td;
etd->et_name = NULL;
break;
}
}
}
}
}
return 0;
}
/*
* Called by the interpreter to do any final clearing up, just in case the
* interpreter will re-start.
*/
static void finalise(void)
{
sipExportedModuleDef *em;
/* Mark the Python API as unavailable. */
sipInterpreter = NULL;
/* Handle any delayed dtors. */
for (em = moduleList; em != NULL; em = em->em_next)
if (em->em_ddlist != NULL)
{
em->em_delayeddtors(em->em_ddlist);
/* Free the list. */
do
{
sipDelayedDtor *dd = em->em_ddlist;
em->em_ddlist = dd->dd_next;
sip_api_free(dd);
}
while (em->em_ddlist != NULL);
}
licenseName = NULL;
licenseeName = NULL;
typeName = NULL;
timestampName = NULL;
signatureName = NULL;
/* Release all memory we've allocated directly. */
sipOMFinalise(&cppPyMap);
/* Re-initialise those globals that (might) need it. */
moduleList = NULL;
}
/*
* Register the given Python type.
*/
static int sip_api_register_py_type(PyTypeObject *type)
{
return addPyObjectToList(&sipRegisteredPyTypes, (PyObject *)type);
}
/*
* Find the registered type with the given name. Raise an exception if it
* couldn't be found.
*/
static PyObject *findPyType(const char *name)
{
sipPyObject *po;
for (po = sipRegisteredPyTypes; po != NULL; po = po->next)
{
PyObject *type = po->object;
if (strcmp(((PyTypeObject *)type)->tp_name, name) == 0)
return type;
}
PyErr_Format(PyExc_RuntimeError, "%s is not a registered type", name);
return NULL;
}
/*
* Add a wrapped C/C++ pointer to the list of delayed dtors.
*/
static void sip_api_add_delayed_dtor(sipSimpleWrapper *sw)
{
void *ptr;
const sipClassTypeDef *ctd;
sipExportedModuleDef *em;
if ((ptr = getPtrTypeDef(sw, &ctd)) == NULL)
return;
/* Find the defining module. */
for (em = moduleList; em != NULL; em = em->em_next)
{
int i;
for (i = 0; i < em->em_nrtypes; ++i)
if (em->em_types[i] == (const sipTypeDef *)ctd)
{
sipDelayedDtor *dd;
if ((dd = sip_api_malloc(sizeof (sipDelayedDtor))) == NULL)
return;
/* Add to the list. */
dd->dd_ptr = ptr;
dd->dd_name = sipPyNameOfContainer(&ctd->ctd_container,
(sipTypeDef *)ctd);
dd->dd_isderived = sipIsDerived(sw);
dd->dd_next = em->em_ddlist;
em->em_ddlist = dd;
return;
}
}
}
/*
* A wrapper around the Python memory allocater that will raise an exception if
* if the allocation fails.
*/
void *sip_api_malloc(size_t nbytes)
{
void *mem;
if ((mem = PyMem_Malloc(nbytes)) == NULL)
PyErr_NoMemory();
return mem;
}
/*
* A wrapper around the Python memory de-allocater.
*/
void sip_api_free(void *mem)
{
PyMem_Free(mem);
}
/*
* Extend a Python slot by looking in other modules to see if there is an
* extender function that can handle the arguments.
*/
static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod,
sipPySlotType st, const sipTypeDef *td, PyObject *arg0,
PyObject *arg1)
{
sipExportedModuleDef *em;
/* Go through each module. */
for (em = moduleList; em != NULL; em = em->em_next)
{
sipPySlotExtenderDef *ex;
/* Skip the module that couldn't handle the arguments. */
if (em == mod)
continue;
/* Skip if the module doesn't have any extenders. */
if (em->em_slotextend == NULL)
continue;
/* Go through each extender. */
for (ex = em->em_slotextend; ex->pse_func != NULL; ++ex)
{
PyObject *res;
/* Skip if not the right slot type. */
if (ex->pse_type != st)
continue;
/* Check against the type if one was given. */
if (td != NULL && td != getGeneratedType(&ex->pse_class, NULL))
continue;
PyErr_Clear();
res = ((binaryfunc)ex->pse_func)(arg0, arg1);
if (res != Py_NotImplemented)
return res;
}
}
/* The arguments couldn't handled anywhere. */
PyErr_Clear();
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
/*
* Call the Python re-implementation of a C++ virtual.
*/
static PyObject *sip_api_call_method(int *isErr, PyObject *method,
const char *fmt, ...)
{
PyObject *args, *res;
va_list va;
va_start(va,fmt);
if ((args = PyTuple_New(strlen(fmt))) != NULL && buildObject(args,fmt,va) != NULL)
res = PyEval_CallObject(method,args);
else
{
res = NULL;
if (isErr != NULL)
*isErr = TRUE;
}
Py_XDECREF(args);
va_end(va);
return res;
}
/*
* Build a result object based on a format string.
*/
static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...)
{
PyObject *res = NULL;
int badfmt, tupsz;
va_list va;
va_start(va,fmt);
/* Basic validation of the format string. */
badfmt = FALSE;
if (*fmt == '(')
{
char *ep;
if ((ep = strchr(fmt,')')) == NULL || ep[1] != '\0')
badfmt = TRUE;
else
tupsz = ep - fmt - 1;
}
else if (strlen(fmt) == 1)
tupsz = -1;
else
badfmt = TRUE;
if (badfmt)
PyErr_Format(PyExc_SystemError,"sipBuildResult(): invalid format string \"%s\"",fmt);
else if (tupsz < 0 || (res = PyTuple_New(tupsz)) != NULL)
res = buildObject(res,fmt,va);
va_end(va);
if (res == NULL && isErr != NULL)
*isErr = TRUE;
return res;
}
/*
* Get the values off the stack and put them into an object.
*/
static PyObject *buildObject(PyObject *obj, const char *fmt, va_list va)
{
char ch, termch;
int i;
/*
* The format string has already been checked that it is properly formed if
* it is enclosed in parenthesis.
*/
if (*fmt == '(')
{
termch = ')';
++fmt;
}
else
termch = '\0';
i = 0;
while ((ch = *fmt++) != termch)
{
PyObject *el;
switch (ch)
{
case 'g':
{
char *s;
SIP_SSIZE_T l;
s = va_arg(va, char *);
l = va_arg(va, SIP_SSIZE_T);
if (s != NULL)
{
el = SIPBytes_FromStringAndSize(s, l);
}
else
{
Py_INCREF(Py_None);
el = Py_None;
}
}
break;
case 'G':
#if defined(HAVE_WCHAR_H)
{
wchar_t *s;
SIP_SSIZE_T l;
s = va_arg(va, wchar_t *);
l = va_arg(va, SIP_SSIZE_T);
if (s != NULL)
el = PyUnicode_FromWideChar(s, l);
else
{
Py_INCREF(Py_None);
el = Py_None;
}
}
#else
raiseNoWChar();
el = NULL;
#endif
break;
case 'b':
el = PyBool_FromLong(va_arg(va,int));
break;
case 'c':
{
char c = va_arg(va, int);
el = SIPBytes_FromStringAndSize(&c, 1);
}
break;
case 'a':
{
char c = va_arg(va, int);
#if PY_MAJOR_VERSION >= 3
el = PyUnicode_FromStringAndSize(&c, 1);
#else
el = PyString_FromStringAndSize(&c, 1);
#endif
}
break;
case 'w':
#if defined(HAVE_WCHAR_H)
{
wchar_t c = va_arg(va, int);
el = PyUnicode_FromWideChar(&c, 1);
}
#else
raiseNoWChar();
el = NULL;
#endif
break;
case 'E':
{
/* This is deprecated. */
int ev = va_arg(va, int);
PyTypeObject *et = va_arg(va, PyTypeObject *);
el = sip_api_convert_from_enum(ev,
((const sipEnumTypeObject *)et)->type);
}
break;
case 'F':
{
int ev = va_arg(va, int);
const sipTypeDef *td = va_arg(va, const sipTypeDef *);
el = sip_api_convert_from_enum(ev, td);
}
break;
case 'd':
case 'f':
el = PyFloat_FromDouble(va_arg(va,double));
break;
case 'e':
case 'h':
case 'i':
#if PY_MAJOR_VERSION >= 3
el = PyLong_FromLong(va_arg(va, int));
#else
el = PyInt_FromLong(va_arg(va, int));
#endif
break;
case 'l':
el = PyLong_FromLong(va_arg(va, long));
break;
case 'm':
el = PyLong_FromUnsignedLong(va_arg(va, unsigned long));
break;
case 'n':
#if defined(HAVE_LONG_LONG)
el = PyLong_FromLongLong(va_arg(va, PY_LONG_LONG));
#else
el = PyLong_FromLong(va_arg(va, long));
#endif
break;
case 'o':
#if defined(HAVE_LONG_LONG)
el = PyLong_FromUnsignedLongLong(va_arg(va, unsigned PY_LONG_LONG));
#else
el = PyLong_FromUnsignedLong(va_arg(va, unsigned long));
#endif
break;
case 's':
{
char *s = va_arg(va, char *);
if (s != NULL)
{
el = SIPBytes_FromString(s);
}
else
{
Py_INCREF(Py_None);
el = Py_None;
}
}
break;
case 'A':
{
char *s = va_arg(va, char *);
if (s != NULL)
#if PY_MAJOR_VERSION >= 3
el = PyUnicode_FromString(s);
#else
el = PyString_FromString(s);
#endif
else
{
Py_INCREF(Py_None);
el = Py_None;
}
}
break;
case 'x':
#if defined(HAVE_WCHAR_H)
{
wchar_t *s = va_arg(va, wchar_t *);
if (s != NULL)
el = PyUnicode_FromWideChar(s, (SIP_SSIZE_T)wcslen(s));
else
{
Py_INCREF(Py_None);
el = Py_None;
}
}
#else
raiseNoWChar();
el = NULL;
#endif
break;
case 't':
case 'u':
el = PyLong_FromUnsignedLong(va_arg(va, unsigned));
break;
case 'B':
{
/* This is deprecated. */
void *p = va_arg(va,void *);
sipWrapperType *wt = va_arg(va, sipWrapperType *);
PyObject *xfer = va_arg(va, PyObject *);
el = sip_api_convert_from_new_type(p, wt->type, xfer);
}
break;
case 'N':
{
void *p = va_arg(va, void *);
const sipTypeDef *td = va_arg(va, const sipTypeDef *);
PyObject *xfer = va_arg(va, PyObject *);
el = sip_api_convert_from_new_type(p, td, xfer);
}
break;
case 'C':
{
/* This is deprecated. */
void *p = va_arg(va,void *);
sipWrapperType *wt = va_arg(va, sipWrapperType *);
PyObject *xfer = va_arg(va, PyObject *);
el = sip_api_convert_from_type(p, wt->type, xfer);
}
break;
case 'D':
{
void *p = va_arg(va, void *);
const sipTypeDef *td = va_arg(va, const sipTypeDef *);
PyObject *xfer = va_arg(va, PyObject *);
el = sip_api_convert_from_type(p, td, xfer);
}
break;
case 'r':
{
void *p = va_arg(va, void *);
SIP_SSIZE_T l = va_arg(va, SIP_SSIZE_T);
const sipTypeDef *td = va_arg(va, const sipTypeDef *);
el = convertToSequence(p, l, td);
}
break;
case 'R':
el = va_arg(va,PyObject *);
break;
case 'S':
el = va_arg(va,PyObject *);
Py_INCREF(el);
break;
case 'V':
el = sip_api_convert_from_void_ptr(va_arg(va, void *));
break;
default:
PyErr_Format(PyExc_SystemError,"buildObject(): invalid format character '%c'",ch);
el = NULL;
}
if (el == NULL)
{
Py_XDECREF(obj);
return NULL;
}
if (obj == NULL)
return el;
PyTuple_SET_ITEM(obj,i,el);
++i;
}
return obj;
}
/*
* Parse a result object based on a format string.
*/
static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res,
const char *fmt, ...)
{
int tupsz, rc = 0;
sipSimpleWrapper *self = NULL;
va_list va;
va_start(va,fmt);
/* Get self if it is provided. */
if (*fmt == 'S')
{
self = va_arg(va, sipSimpleWrapper *);
++fmt;
}
/* Basic validation of the format string. */
if (*fmt == '(')
{
char ch;
const char *cp = ++fmt;
tupsz = 0;
while ((ch = *cp++) != ')')
{
if (ch == '\0')
{
PyErr_Format(PyExc_SystemError, "sipParseResult(): invalid format string \"%s\"", fmt - 1);
rc = -1;
break;
}
/*
* Some format characters have a sub-format so skip the character
* and count the sub-format character next time round.
*/
if (strchr("HDC", ch) == NULL)
++tupsz;
}
if (rc == 0)
if (!PyTuple_Check(res) || PyTuple_GET_SIZE(res) != tupsz)
{
sip_api_bad_catcher_result(method);
rc = -1;
}
}
else
tupsz = -1;
if (rc == 0)
{
char ch;
int i = 0;
while ((ch = *fmt++) != '\0' && ch != ')' && rc == 0)
{
PyObject *arg;
int invalid = FALSE;
if (tupsz > 0)
{
arg = PyTuple_GET_ITEM(res,i);
++i;
}
else
arg = res;
switch (ch)
{
case 'g':
{
const char **p = va_arg(va, const char **);
SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
if (parseBytes_AsCharArray(arg, p, szp) < 0)
invalid = TRUE;
}
break;
case 'G':
#if defined(HAVE_WCHAR_H)
{
wchar_t **p = va_arg(va, wchar_t **);
SIP_SSIZE_T *szp = va_arg(va, SIP_SSIZE_T *);
if (parseWCharArray(arg, p, szp) < 0)
invalid = TRUE;
}
#else
raiseNoWChar();
invalid = TRUE;
#endif
break;
case 'b':
{
int v = SIPLong_AsLong(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
sipSetBool(va_arg(va, void *), v);
}
break;
case 'c':
{
char *p = va_arg(va, char *);
if (parseBytes_AsChar(arg, p) < 0)
invalid = TRUE;
}
break;
case 'a':
{
char *p = va_arg(va, char *);
int enc;
switch (*fmt++)
{
case 'A':
enc = parseString_AsASCIIChar(arg, p);
break;
case 'L':
enc = parseString_AsLatin1Char(arg, p);
break;
case '8':
enc = parseString_AsUTF8Char(arg, p);
break;
default:
enc = -1;
}
if (enc < 0)
invalid = TRUE;
}
break;
case 'w':
#if defined(HAVE_WCHAR_H)
{
wchar_t *p = va_arg(va, wchar_t *);
if (parseWChar(arg, p) < 0)
invalid = TRUE;
}
#else
raiseNoWChar();
invalid = TRUE;
#endif
break;
case 'd':
{
double v = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,double *) = v;
}
break;
case 'E':
{
/* This is deprecated. */
PyTypeObject *et = va_arg(va, PyTypeObject *);
int *p = va_arg(va, int *);
if (sip_api_can_convert_to_enum(arg, ((sipEnumTypeObject *)et)->type))
*p = SIPLong_AsLong(arg);
else
invalid = TRUE;
}
break;
case 'F':
{
sipTypeDef *td = va_arg(va, sipTypeDef *);
int *p = va_arg(va, int *);
if (sip_api_can_convert_to_enum(arg, td))
*p = SIPLong_AsLong(arg);
else
invalid = TRUE;
}
break;
case 'f':
{
float v = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,float *) = v;
}
break;
case 'h':
{
short v = SIPLong_AsLong(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va, short *) = v;
}
break;
case 't':
{
unsigned short v = sip_api_long_as_unsigned_long(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,unsigned short *) = v;
}
break;
case 'e':
case 'i':
{
int v = SIPLong_AsLong(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va, int *) = v;
}
break;
case 'u':
{
unsigned v = sip_api_long_as_unsigned_long(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,unsigned *) = v;
}
break;
case 'l':
{
long v = PyLong_AsLong(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,long *) = v;
}
break;
case 'm':
{
unsigned long v = sip_api_long_as_unsigned_long(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va, unsigned long *) = v;
}
break;
case 'n':
{
#if defined(HAVE_LONG_LONG)
PY_LONG_LONG v = PyLong_AsLongLong(arg);
#else
long v = PyLong_AsLong(arg);
#endif
if (PyErr_Occurred())
invalid = TRUE;
else
#if defined(HAVE_LONG_LONG)
*va_arg(va, PY_LONG_LONG *) = v;
#else
*va_arg(va, long *) = v;
#endif
}
break;
case 'o':
{
#if defined(HAVE_LONG_LONG)
unsigned PY_LONG_LONG v = PyLong_AsUnsignedLongLong(arg);
#else
unsigned long v = PyLong_AsUnsignedLong(arg);
#endif
if (PyErr_Occurred())
invalid = TRUE;
else
#if defined(HAVE_LONG_LONG)
*va_arg(va, unsigned PY_LONG_LONG *) = v;
#else
*va_arg(va, unsigned long *) = v;
#endif
}
break;
case 's':
{
/* This is deprecated. */
const char **p = va_arg(va, const char **);
if (parseBytes_AsString(arg, p) < 0)
invalid = TRUE;
}
break;
case 'A':
{
int key = va_arg(va, int);
const char **p = va_arg(va, const char **);
PyObject *keep;
switch (*fmt++)
{
case 'A':
keep = parseString_AsASCIIString(arg, p);
break;
case 'L':
keep = parseString_AsLatin1String(arg, p);
break;
case '8':
keep = parseString_AsUTF8String(arg, p);
break;
default:
keep = NULL;
}
if (keep == NULL)
invalid = TRUE;
else
sip_api_keep_reference((PyObject *)self, key, keep);
}
break;
case 'B':
{
int key = va_arg(va, int);
const char **p = va_arg(va, const char **);
if (parseBytes_AsString(arg, p) < 0)
invalid = TRUE;
else
{
Py_INCREF(arg);
sip_api_keep_reference((PyObject *)self, key, arg);
}
}
break;
case 'x':
#if defined(HAVE_WCHAR_H)
{
wchar_t **p = va_arg(va, wchar_t **);
if (parseWCharString(arg, p) < 0)
invalid = TRUE;
}
#else
raiseNoWChar();
invalid = TRUE;
#endif
break;
case 'C':
{
/* This is deprecated. */
if (*fmt == '\0')
invalid = TRUE;
else
{
int flags = *fmt++ - '0';
int iserr = FALSE;
sipWrapperType *type;
void **cpp;
int *state;
type = va_arg(va, sipWrapperType *);
if (flags & FMT_RP_NO_STATE_DEPR)
state = NULL;
else
state = va_arg(va, int *);
cpp = va_arg(va, void **);
*cpp = sip_api_force_convert_to_type(arg, type->type, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), state, &iserr);
if (iserr)
invalid = TRUE;
}
}
break;
case 'D':
{
/* This is deprecated. */
if (*fmt == '\0')
invalid = TRUE;
else
{
int flags = *fmt++ - '0';
int iserr = FALSE;
const sipTypeDef *td;
void **cpp;
int *state;
td = va_arg(va, const sipTypeDef *);
if (flags & FMT_RP_NO_STATE_DEPR)
state = NULL;
else
state = va_arg(va, int *);
cpp = va_arg(va, void **);
*cpp = sip_api_force_convert_to_type(arg, td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), state, &iserr);
if (iserr)
invalid = TRUE;
}
}
break;
case 'H':
{
if (*fmt == '\0')
invalid = TRUE;
else
{
int flags = *fmt++ - '0';
int iserr = FALSE, state;
const sipTypeDef *td;
void *cpp, *val;
td = va_arg(va, const sipTypeDef *);
cpp = va_arg(va, void **);
val = sip_api_force_convert_to_type(arg, td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), &state, &iserr);
if (iserr)
{
invalid = TRUE;
}
else if (flags & FMT_RP_MAKE_COPY)
{
sipAssignFunc assign_helper;
if (sipTypeIsMapped(td))
assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign;
else
assign_helper = ((const sipClassTypeDef *)td)->ctd_assign;
assert(assign_helper != NULL);
assign_helper(cpp, 0, val);
sip_api_release_type(val, td, state);
}
else
{
*(void **)cpp = val;
}
}
}
break;
case 'N':
{
PyTypeObject *type = va_arg(va,PyTypeObject *);
PyObject **p = va_arg(va,PyObject **);
if (arg == Py_None || PyObject_TypeCheck(arg,type))
{
Py_INCREF(arg);
*p = arg;
}
else
invalid = TRUE;
}
break;
case 'O':
Py_INCREF(arg);
*va_arg(va,PyObject **) = arg;
break;
case 'T':
{
PyTypeObject *type = va_arg(va,PyTypeObject *);
PyObject **p = va_arg(va,PyObject **);
if (PyObject_TypeCheck(arg,type))
{
Py_INCREF(arg);
*p = arg;
}
else
invalid = TRUE;
}
break;
case 'V':
{
void *v = sip_api_convert_to_void_ptr(arg);
if (PyErr_Occurred())
invalid = TRUE;
else
*va_arg(va,void **) = v;
}
break;
case 'Z':
if (arg != Py_None)
invalid = TRUE;
break;
default:
PyErr_Format(PyExc_SystemError,"sipParseResult(): invalid format character '%c'",ch);
rc = -1;
}
if (invalid)
{
sip_api_bad_catcher_result(method);
rc = -1;
break;
}
}
}
va_end(va);
if (isErr != NULL && rc < 0)
*isErr = TRUE;
return rc;
}
/*
* A thin wrapper around PyLong_AsUnsignedLong() that works around a bug in
* Python versions prior to v2.4 where an integer (or a named enum) causes an
* error.
*/
static unsigned long sip_api_long_as_unsigned_long(PyObject *o)
{
#if PY_VERSION_HEX < 0x02040000
if (o != NULL && !PyLong_Check(o) && PyInt_Check(o))
{
long v = PyInt_AsLong(o);
if (v < 0)
{
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to unsigned long");
return (unsigned long)-1;
}
return v;
}
#endif
return PyLong_AsUnsignedLong(o);
}
/*
* Parse the arguments to a C/C++ function without any side effects.
*/
static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs,
const char *fmt, ...)
{
int ok;
va_list va;
va_start(va, fmt);
ok = parseKwdArgs(parseErrp, sipArgs, NULL, NULL, NULL, fmt, va);
va_end(va);
return ok;
}
/*
* Parse the positional and/or keyword arguments to a C/C++ function without
* any side effects.
*/
static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs,
PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
const char *fmt, ...)
{
int ok;
va_list va;
/* Initialise the return of any unused keyword arguments. */
if (unused != NULL)
*unused = NULL;
va_start(va, fmt);
ok = parseKwdArgs(parseErrp, sipArgs, sipKwdArgs, kwdlist, unused, fmt,
va);
va_end(va);
/* Release any unused arguments if the parse failed. */
if (!ok && unused != NULL)
{
Py_XDECREF(*unused);
}
return ok;
}
/*
* Parse the arguments to a C/C++ function without any side effects.
*/
static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs,
PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused,
const char *fmt, va_list va_orig)
{
int no_tmp_tuple, ok, selfarg;
sipSimpleWrapper *self;
PyObject *single_arg;
va_list va;
/* Previous second pass errors stop subsequent parses. */
if (*parseErrp != NULL && !PyList_Check(*parseErrp))
return FALSE;
/*
* See if we are parsing a single argument. In current versions we are
* told explicitly by the first character of the format string. In earlier
* versions we guessed (sometimes wrongly).
*/
if (*fmt == '1')
{
++fmt;
no_tmp_tuple = FALSE;
}
else
no_tmp_tuple = PyTuple_Check(sipArgs);
if (no_tmp_tuple)
{
Py_INCREF(sipArgs);
}
else if ((single_arg = PyTuple_New(1)) != NULL)
{
Py_INCREF(sipArgs);
PyTuple_SET_ITEM(single_arg, 0, sipArgs);
sipArgs = single_arg;
}
else
{
/* Stop all parsing and indicate an exception has been raised. */
Py_XDECREF(*parseErrp);
*parseErrp = Py_None;
Py_INCREF(Py_None);
return FALSE;
}
/*
* The first pass checks all the types and does conversions that are cheap
* and have no side effects.
*/
va_copy(va, va_orig);
ok = parsePass1(parseErrp, &self, &selfarg, sipArgs, sipKwdArgs, kwdlist,
unused, fmt, va);
va_end(va);
if (ok)
{
/*
* The second pass does any remaining conversions now that we know we
* have the right signature.
*/
va_copy(va, va_orig);
ok = parsePass2(self, selfarg, sipArgs, sipKwdArgs, kwdlist, fmt, va);
va_end(va);
/* Remove any previous failed parses. */
Py_XDECREF(*parseErrp);
if (ok)
{
*parseErrp = NULL;
}
else