📄 siplib.c
字号:
/* * SIP library code. * * Copyright (c) 2006 * Riverbank Computing Limited <info@riverbankcomputing.co.uk> * * 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. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */#include <Python.h>#include <stdio.h>#include <stdarg.h>#include <stddef.h>#include <string.h>#include "sip.h"#include "sipint.h"/* * These are the functions that make up the public and private SIP API. */static void sip_api_bad_catcher_result(PyObject *method);static void sip_api_bad_length_for_slice(int seqlen,int slicelen);static PyObject *sip_api_build_result(int *isErr,char *fmt,...);static PyObject *sip_api_call_method(int *isErr,PyObject *method,char *fmt, ...);static PyObject *sip_api_class_name(PyObject *self);static int sip_api_convert_from_sequence_index(int idx,int len);static int sip_api_can_convert_to_instance(PyObject *pyObj, sipWrapperType *type, int flags);static int sip_api_can_convert_to_mapped_type(PyObject *pyObj, const sipMappedType *mt, int flags);static void *sip_api_convert_to_instance(PyObject *pyObj, sipWrapperType *type, PyObject *transferObj, int flags, int *statep, int *iserrp);static void *sip_api_convert_to_mapped_type(PyObject *pyObj, const sipMappedType *mt, PyObject *transferObj, int flags, int *statep, int *iserrp);static void *sip_api_force_convert_to_instance(PyObject *pyObj, sipWrapperType *type, PyObject *transferObj, int flags, int *statep, int *iserrp);static void *sip_api_force_convert_to_mapped_type(PyObject *pyObj, const sipMappedType *mt, PyObject *transferObj, int flags, int *statep, int *iserrp);static void sip_api_release_instance(void *cpp, sipWrapperType *type, int state);static void sip_api_release_mapped_type(void *cpp, const sipMappedType *mt, int state);static PyObject *sip_api_convert_from_new_instance(void *cpp, sipWrapperType *type, PyObject *transferObj);static PyObject *sip_api_convert_from_mapped_type(void *cpp, const sipMappedType *mt, PyObject *transferObj);static void *sip_api_convert_to_cpp(PyObject *sipSelf,sipWrapperType *type, int *iserrp);static int sip_api_get_state(PyObject *transferObj);static const sipMappedType *sip_api_find_mapped_type(const char *type);static PyObject *sip_api_get_wrapper(void *cppPtr,sipWrapperType *type);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, char *fmt,...);static void sip_api_trace(unsigned mask,const char *fmt,...);static void sip_api_transfer(PyObject *self,int toCpp);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, PyObject *mod_dict);static int sip_api_parse_args(int *argsParsedp,PyObject *sipArgs,char *fmt, ...);static int sip_api_parse_pair(int *argsParsedp,PyObject *sipArg0, PyObject *sipArg1,char *fmt,...);static void sip_api_common_ctor(sipMethodCache *cache,int nrmeths);static void sip_api_common_dtor(sipWrapper *sipSelf);static void *sip_api_convert_to_void_ptr(PyObject *obj);static void sip_api_no_function(int argsParsed,char *func);static void sip_api_no_method(int argsParsed,char *classname,char *method);static void sip_api_abstract_method(char *classname,char *method);static void sip_api_bad_class(const char *classname);static void sip_api_bad_set_type(const char *classname,const char *var);static void *sip_api_get_complex_cpp_ptr(sipWrapper *w);static PyObject *sip_api_is_py_method(sip_gilstate_t *gil,sipMethodCache *pymc, sipWrapper *sipSelf,char *cname, char *mname);static void sip_api_call_hook(char *hookname);static void sip_api_raise_unknown_exception(void);static void sip_api_raise_class_exception(sipWrapperType *type,void *ptr);static void sip_api_raise_sub_class_exception(sipWrapperType *type,void *ptr);static int sip_api_add_class_instance(PyObject *dict,char *name,void *cppPtr, sipWrapperType *wt);static int sip_api_add_mapped_type_instance(PyObject *dict,char *name, void *cppPtr, sipMappedType *mt);static int sip_api_add_enum_instance(PyObject *dict, char *name, int value, PyTypeObject *type);static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg, sipPySlotType st);static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod, sipPySlotType st, sipWrapperType *type, PyObject *arg0, PyObject *arg1);static void sip_api_add_delayed_dtor(sipWrapper *w);static unsigned long sip_api_long_as_unsigned_long(PyObject *o);/* * 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. */ sip_api_bad_catcher_result, sip_api_bad_length_for_slice, sip_api_build_result, sip_api_call_method, sip_api_class_name, sip_api_connect_rx, sip_api_convert_from_sequence_index, sip_api_can_convert_to_instance, sip_api_can_convert_to_mapped_type, sip_api_convert_to_instance, sip_api_convert_to_mapped_type, sip_api_force_convert_to_instance, sip_api_force_convert_to_mapped_type, sip_api_release_instance, sip_api_release_mapped_type, sip_api_convert_from_instance, sip_api_convert_from_new_instance, sip_api_convert_from_mapped_type, sip_api_convert_to_cpp, sip_api_get_state, sip_api_find_mapped_type, sip_api_disconnect_rx, sip_api_emit_signal, sip_api_free, sip_api_get_sender, sip_api_get_wrapper, sip_api_malloc, sip_api_map_int_to_class, sip_api_map_string_to_class, sip_api_parse_result, sip_api_trace, sip_api_transfer, sip_api_transfer_back, sip_api_transfer_to, sip_api_wrapper_check, sip_api_long_as_unsigned_long, /* * The following may be used by Qt support code but by no other * handwritten code. */ sip_api_convert_from_named_enum, sip_api_convert_from_void_ptr, sip_api_free_connection, sip_api_emit_to_slot, sip_api_same_connection, sip_api_convert_rx, /* * The following are not part of the public API. */ sip_api_parse_args, sip_api_parse_pair, sip_api_common_ctor, sip_api_common_dtor, sip_api_convert_to_void_ptr, sip_api_no_function, sip_api_no_method, sip_api_abstract_method, sip_api_bad_class, sip_api_bad_set_type, 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_class_exception, sip_api_raise_sub_class_exception, sip_api_add_class_instance, sip_api_add_enum_instance, sip_api_bad_operator_arg, sip_api_pyslot_extend, sip_api_add_delayed_dtor, sip_api_add_mapped_type_instance,};#define PARSE_OK 0x00000000 /* Parse is Ok so far. */#define PARSE_MANY 0x10000000 /* Too many arguments. */#define PARSE_FEW 0x20000000 /* Too few arguments. */#define PARSE_TYPE 0x30000000 /* Argument with a bad type. */#define PARSE_UNBOUND 0x40000000 /* Unbound method. */#define PARSE_FORMAT 0x50000000 /* Bad format character. */#define PARSE_RAISED 0x60000000 /* Exception already raised. */#define PARSE_STICKY 0x80000000 /* The error sticks. */#define PARSE_MASK 0xf0000000/* * Note that some of the following flags safely share values because they * cannot be used at the same time. */#define FORMAT_DEREF 0x01 /* The pointer will be dereferenced. */#define FORMAT_FACTORY 0x02 /* Implement /Factory/ in a VH. */#define FORMAT_TRANSFER 0x02 /* Implement /Transfer/. */#define FORMAT_NO_STATE 0x04 /* Don't return the C/C++ state. */#define FORMAT_TRANSFER_BACK 0x04 /* Implement /TransferBack/. */#define FORMAT_GET_WRAPPER 0x08 /* Implement /GetWrapper/. */#define FORMAT_NO_CONVERTORS 0x10 /* Suppress any convertors. */#define SIP_MC_FOUND 0x01 /* If we have looked for the method. */#define SIP_MC_ISMETH 0x02 /* If we looked and there was one. */#define sipFoundMethod(m) ((m) -> mcflags & SIP_MC_FOUND)#define sipSetFoundMethod(m) ((m) -> mcflags |= SIP_MC_FOUND)#define sipIsMethod(m) ((m) -> mcflags & SIP_MC_ISMETH)#define sipSetIsMethod(m) ((m) -> mcflags |= SIP_MC_ISMETH)static PyTypeObject sipWrapperType_Type;static sipWrapperType sipWrapper_Type;static PyTypeObject sipVoidPtr_Type;PyInterpreterState *sipInterpreter = NULL;sipQtAPI *sipQtSupport = NULL;sipWrapperType *sipQObjectClass;/* * 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 *clientList = NULL; /* List of registered clients. */static unsigned traceMask = 0; /* The current trace mask. */static sipTypeDef *currentType = NULL; /* The type being created. */static void addSlots(sipWrapperType *wt, sipTypeDef *td);static void initSlots(PyTypeObject *to, PyNumberMethods *nb, PySequenceMethods *sq, PyMappingMethods *mp, sipPySlotDef *slots, int force);static void *findSlot(PyObject *self,sipPySlotType st);static void *findSlotInType(sipTypeDef *td, sipPySlotType st);static int objobjargprocSlot(PyObject *self,PyObject *arg1,PyObject *arg2, sipPySlotType st);static int intobjargprocSlot(PyObject *self,int arg1,PyObject *arg2, sipPySlotType st);static PyObject *buildObject(PyObject *tup,char *fmt,va_list va);static int parsePass1(sipWrapper **selfp,int *selfargp,int *argsParsedp, PyObject *sipArgs,char *fmt,va_list va);static int parsePass2(sipWrapper *self,int selfarg,int nrargs, PyObject *sipArgs,char *fmt,va_list va);static int getSelfFromArgs(sipWrapperType *type,PyObject *args,int argnr, sipWrapper **selfp);static PyObject *createEnumMember(sipTypeDef *td, sipEnumMemberDef *enm);static PyObject *handleGetLazyAttr(PyObject *nameobj,sipWrapperType *wt, sipWrapper *w);static int handleSetLazyAttr(PyObject *nameobj,PyObject *valobj, sipWrapperType *wt,sipWrapper *w);static int getNonStaticVariables(sipWrapperType *wt,sipWrapper *w, PyObject **ndict);static void findLazyAttr(sipWrapperType *wt,char *name,PyMethodDef **pmdp, sipEnumMemberDef **enmp,PyMethodDef **vmdp, sipTypeDef **in);static int compareMethodName(const void *key,const void *el);static int compareEnumMemberName(const void *key,const void *el);static int checkPointer(void *ptr);static void badArgs(int argsParsed,char *classname,char *method);static void finalise(void);static sipWrapperType *createType(sipExportedModuleDef *client, sipTypeDef *type, PyObject *mod_dict);static PyTypeObject *createEnum(sipExportedModuleDef *client, sipEnumDef *ed, PyObject *mod_dict);static const char *getBaseName(const char *name);static PyObject *getBaseNameObject(const char *name);static PyObject *createTypeDict(PyObject *mname);static sipExportedModuleDef *getClassModule(sipEncodedClassDef *enc, sipExportedModuleDef *em);static sipWrapperType *getClassType(sipEncodedClassDef *enc, sipExportedModuleDef *em);static sipWrapperType *convertSubClass(sipWrapperType *type,void **cppPtr);static void *getPtrTypeDef(sipWrapper *self, sipTypeDef **td);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 addEnumInstances(PyObject *dict,sipEnumInstanceDef *ei);static int addSingleEnumInstance(PyObject *dict, char *name, int value, PyTypeObject *type);static int addClassInstances(PyObject *dict,sipClassInstanceDef *ci);static int addSingleClassInstance(PyObject *dict,char *name,void *cppPtr, sipWrapperType *wt,int initflags);static int addLicense(PyObject *dict,sipLicenseDef *lc);static PyObject *cast(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 *transfer(PyObject *self,PyObject *args);static PyObject *transferback(PyObject *self,PyObject *args);static PyObject *transferto(PyObject *self,PyObject *args);static int sipWrapperType_Check(PyObject *op);static void addToParent(sipWrapper *self, sipWrapper *owner);static void removeFromParent(sipWrapper *self);static int findClassArg(sipExportedModuleDef *emd, const char *name, size_t len, sipSigArg *at, int indir);static int findMtypeArg(sipMappedType **mttab, const char *name, size_t len, sipSigArg *at, int indir);static int findEnumArg(sipExportedModuleDef *emd, const char *name, size_t len, sipSigArg *at, int indir);static int sameScopedName(const char *pyname, const char *name, size_t len);static int nameEq(const char *with, const char *name, size_t len);static int isExactWrappedType(sipWrapperType *wt);/* * The Python module initialisation function. */#if defined(SIP_STATIC_MODULE)void initsip(void)#elsePyMODINIT_FUNC initsip(void)#endif{ static PyMethodDef methods[] = { {"cast", cast, METH_VARARGS, NULL}, {"settracemask", setTraceMask, METH_VARARGS, NULL}, {"transfer", transfer, METH_VARARGS, NULL}, {"transferback", transferback, METH_VARARGS, NULL}, {"transferto", transferto, METH_VARARGS, NULL}, {"wrapinstance", wrapInstance, METH_VARARGS, NULL}, {"unwrapinstance", unwrapInstance, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; 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) Py_FatalError("sip: Failed to initialise sip.wrappertype type"); if (PyType_Ready(&sipWrapper_Type.super.type) < 0) Py_FatalError("sip: Failed to initialise sip.wrapper type"); if (PyType_Ready(&sipVoidPtr_Type) < 0) Py_FatalError("sip: Failed to initialise sip.voidptr type"); mod = Py_InitModule("sip",methods); mod_dict = PyModule_GetDict(mod); /* Publish the SIP API. */ if ((obj = PyCObject_FromVoidPtr((void *)&sip_api,NULL)) == NULL) Py_FatalError("sip: Failed to create _C_API object"); rc = PyDict_SetItemString(mod_dict,"_C_API",obj); Py_DECREF(obj); if (rc < 0) Py_FatalError("sip: Failed to add _C_API object to module dictionary"); /* Add the SIP version number, but don't worry about errors. */ if ((obj = PyInt_FromLong(SIP_VERSION)) != NULL) { PyDict_SetItemString(mod_dict, "SIP_VERSION", obj); Py_DECREF(obj); } if ((obj = PyString_FromString(SIP_VERSION_STR)) != 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, "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); sipQtSupport = NULL; /* * Get the current interpreter. This will be shared between * all threads. */ sipInterpreter = PyThreadState_Get() -> interp; }}/* * 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;}/* * 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 (!sip_api_wrapper_check(owner)) { PyErr_Format(PyExc_TypeError,"transferto() argument 2 must be sip.wrapper, not %s",owner->ob_type->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;}/* * Transfer the ownership of an instance. This is deprecated. */static PyObject *transfer(PyObject *self,PyObject *args){ PyObject *w; int toCpp; if (PyArg_ParseTuple(args,"O!i:transfer",&sipWrapper_Type,&w,&toCpp)) { if (toCpp) sip_api_transfer_to(w, NULL); else 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){ sipWrapper *w; sipWrapperType *wt, *type; void *addr; PyTypeObject *ft, *tt; if (!PyArg_ParseTuple(args,"O!O!:cast",&sipWrapper_Type,&w,&sipWrapperType_Type,&wt)) return NULL; ft = ((PyObject *)w) -> ob_type; tt = (PyTypeObject *)wt; if (ft == tt || PyType_IsSubtype(tt, ft)) type = NULL; else if (PyType_IsSubtype(ft, tt)) type = wt; 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(w, type)) == 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,NULL,(w->flags | SIP_NOT_IN_MAP) & ~SIP_PY_OWNED);}/* * Unwrap an instance. */static PyObject *unwrapInstance(PyObject *self,PyObject *args){ sipWrapper *w; if (PyArg_ParseTuple(args,"O!:unwrapinstance",&sipWrapper_Type,&w)) { 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(w,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_instance((void *)addr, wt, NULL); return NULL;}/* * Register a client module. A negative value is returned and an exception * raised if there was an error. Not normally needed by handwritten code.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -