diff --git a/build.py b/build.py index ef6375e6..18a886ba 100755 --- a/build.py +++ b/build.py @@ -46,7 +46,6 @@ from buildtools.config import Config, msg, opj, posixjoin, loadETG, etg2sip, fi getVcsRev, runcmd, textfile_open, getSipFiles, \ getVisCVersion, getToolsPlatformName, updateLicenseFiles, \ TemporaryDirectory, getMSVCInfo -from buildtools.wxpysip import sip_runner import buildtools.version as version @@ -1259,7 +1258,7 @@ def cmd_sip(options, args): base = os.path.basename(os.path.splitext(src_name)[0]) sbf = posixjoin(cfg.SIPOUT, base) + '.sbf' pycode = base[1:] # remove the leading _ - pycode = posixjoin(cfg.PKGDIR, pycode) + '.py' + pycode = opj(cfg.ROOT_DIR, cfg.PKGDIR, pycode) + '.py' # Check if any of the included files are newer than the .sbf file # produced by the previous run of sip. If not then we don't need to @@ -1277,23 +1276,54 @@ def cmd_sip(options, args): # module's .py file pycode = 'pycode'+base+':'+pycode - sip_runner(src_name, - abi_version = cfg.SIP_ABI, # siplib abi version - warnings = True, # enable warning messages - docstrings = True, # enable the automatic generation of docstrings - release_gil = True, # always release and reacquire the GIL - sip_module = 'wx.siplib', # the fully qualified name of the sip module - sbf_file=sbf, # File to write the generated file lists to - exceptions = False, # enable support for exceptions - tracing = cfg.SIP_TRACE, # generate code with tracing enabled - sources_dir = tmpdir, # the name of the code directory - extracts = [pycode], # add to the list of extracts to generate - pyi_extract=pyi_extract, # the name of the .pyi stub file - include_dirs = [ - os.path.join(phoenixDir(), 'src'), - os.path.join(phoenixDir(), 'sip', 'gen'), - ]) + # Write out a pyproject.toml to configure sip + pyproject_toml = ( + '[build-system]\n' + 'requires = ["sip >=5.5.0, <7"]\n' + 'build-backend = "sipbuild.api"\n' + '\n' + '[tool.sip.metadata]\n' + 'name = "{base}"\n' + '\n' + '[tool.sip.bindings.{base}]\n' + 'docstrings = true\n' + 'release-gil = true\n' + 'exceptions = false\n' + 'tracing = {tracing}\n' + 'protected-is-public = false\n' + 'generate-extracts = [\'{extracts}\']\n' + 'pep484-pyi = false\n' + '\n' + '[tool.sip.project]\n' + 'abi-version = "{abi_version}"\n' + 'sip-files-dir = \'{sip_gen_dir}\'\n' + 'sip-include-dirs = [\'{src_dir}\']\n' + 'sip-module = "wx.siplib"\n' + ).format( + base=base, + abi_version=cfg.SIP_ABI, + tracing=str(cfg.SIP_TRACE).lower(), + extracts=pycode, + src_dir=opj(phoenixDir(), 'src'), + sip_gen_dir=opj(phoenixDir(), 'sip', 'gen'), + ) + with open(opj(tmpdir, 'pyproject.toml'), 'w') as f: + f.write(pyproject_toml) + sip_pwd = pushDir(tmpdir) + cmd = 'sip-build --no-compile' + runcmd(cmd) + del sip_pwd + + # Write out a sip build file (no longer done by sip itself) + sip_tmp_out_dir = opj(tmpdir, 'build', base) + sip_pwd = pushDir(sip_tmp_out_dir) + header = glob.glob('*.h')[0] + sources = glob.glob('*.cpp') + del sip_pwd + with open(sbf, 'w') as f: + f.write("sources = {}\n".format(' '.join(sources))) + f.write("headers = {}\n".format(header)) classesNeedingClassInfo = { 'sip_corewxTreeCtrl.cpp' : 'wxTreeCtrl', } @@ -1302,7 +1332,7 @@ def cmd_sip(options, args): srcTxt = f.read() if keepHashLines: # Either just fix the pathnames in the #line lines... - srcTxt = srcTxt.replace(tmpdir, cfg.SIPOUT) + srcTxt = srcTxt.replace(sip_tmp_out_dir, cfg.SIPOUT) else: # ...or totally remove them by replacing those lines with '' import re @@ -1333,7 +1363,7 @@ def cmd_sip(options, args): # Check each file in tmpdir to see if it is different than the same file # in cfg.SIPOUT. If so then copy the new one to cfg.SIPOUT, otherwise # ignore it. - for src in glob.glob(tmpdir + '/*'): + for src in glob.glob(sip_tmp_out_dir + '/*'): dest = opj(cfg.SIPOUT, os.path.basename(src)) if not os.path.exists(dest): msg('%s is a new file, copying...' % os.path.basename(src)) @@ -1356,6 +1386,17 @@ def cmd_sip(options, args): # Remove tmpdir and its contents shutil.rmtree(tmpdir) + # Generate sip module code + deleteIfExists(cfg.SIPINC) + with tempfile.TemporaryDirectory() as tmpdir: + cmd = 'sip-module --sdist --abi-version {} --target-dir {} wx.siplib'.format(cfg.SIP_ABI, tmpdir) + runcmd(cmd) + tf_name = glob.glob(tmpdir + '/*.tar*')[0] + tf_dir = os.path.splitext(os.path.splitext(tf_name)[0])[0] + with tarfile.open(tf_name) as tf: + tf.extractall(tmpdir) + shutil.move(tf_dir, cfg.SIPINC) + def cmd_touch(options, args): cmdTimer = CommandTimer('touch') diff --git a/buildtools/wxpysip.py b/buildtools/wxpysip.py deleted file mode 100644 index c58102b8..00000000 --- a/buildtools/wxpysip.py +++ /dev/null @@ -1,110 +0,0 @@ -#---------------------------------------------------------------------- -# Name: buildtools.wxpysip -# Purpose: Code to help migrate to SIP 5 with as little disruption -# as possible. -# -# Author: Robin Dunn -# -# Created: 4-Jan-2021 -# Copyright: (c) 2021 by Total Control Software -# License: wxWindows License -#---------------------------------------------------------------------- - -# NOTE: This code is mostly copied, adapted, and extended from the -# sipbuild.legacy.sip5 module. The main intent is to make it easy to run -# sip the same way as the legacy sip5 entry point, but without needing to -# run a subprocess, and to also add a little missing sip 4 functionality -# that we were depending on with the old SIP. -import os - -from sipbuild.code_generator import (set_globals, parse, generateCode, - generateExtracts, generateAPI, generateXML, generateTypeHints) -from sipbuild.exceptions import handle_exception, UserException -from sipbuild.module import resolve_abi_version -from sipbuild.version import SIP_VERSION, SIP_VERSION_STR - - -def sip_runner( - specification, # the name of the specification file [default stdin] - sources_dir=None, # the name of the code output directory [default not generated] - include_dirs=[], # add to the list of directories to search when importing or including .sip files - warnings=False, # enable warning messages [default disabled] - docstrings=False, # enable the automatic generation of docstrings [default disabled] - release_gil=False, # always release and reacquire the GIL [default only when specified] - sip_module=None, # the fully qualified name of the sip module - api_extract=None, # the name of the QScintilla API file [default not generated - exceptions=False, # enable support for C++ exceptions [default disabled] - tracing=False, # generate code with tracing enabled [default disabled] - extracts=[], # add to the list of extracts to generate - pyi_extract=None, # the name of the .pyi stub file [default not generated] - sbf_file=None, # File to write the generated file lists to [default not generated] - abi_version=None, # the sip ABI version - backstops=[], # add to the list of timeline backstops - py_debug=False, # generate code for a debug build of Python - warnings_are_errors=False, # warnings are handled as errors - parts=0, # split the generated code into files [default 1 per class] - xml_extract=None, # file to write sip xml to - protected_is_public=False, # enable the protected/public hack [default disabled] - source_suffix=None, # the suffix to use for C or C++ source files [default \".c\" or \".cpp\"] - tags=[], # add to the list of versions/platforms to generate code for - disabled_features=[], # add to the list of disabled features - ): - - print("Running SIP code generator on: {}".format(specification)) - - generated_files = [] - try: - # The code generator requires the name of the sip module. - if sources_dir is not None and sip_module is None: - raise UserException("the name of the sip module must be given") - - # Check the ABI version. - abi_major, abi_minor = resolve_abi_version(abi_version).split('.') - - # Set the globals. - set_globals(SIP_VERSION, SIP_VERSION_STR, int(abi_major), int(abi_minor), - UserException, include_dirs) - - # Parse the input file. - pt, _, _, _, tags, disabled_features = parse(specification, - (xml_extract is None), tags, backstops, disabled_features, - protected_is_public) - - # Generate the bindings. - if sources_dir is not None: - generated_files = generateCode(pt, sources_dir, source_suffix, - exceptions, tracing, release_gil, parts, tags, - disabled_features, docstrings, py_debug, sip_module) - - if sbf_file is not None: - generateBuildFile(sbf_file, generated_files) - - # Generate any extracts. - generateExtracts(pt, extracts) - - # Generate the API file. - if api_extract is not None: - generateAPI(pt, api_extract) - - # Generate the type hints file. - if pyi_extract is not None: - generateTypeHints(pt, pyi_extract) - - # Generate the XML file. - if xml_extract is not None: - generateXML(pt, xml_extract) - - except Exception as e: - handle_exception(e) - - return generated_files - - -def generateBuildFile(sbf_file, generated_files): - header, sources = generated_files - header = os.path.basename(header) - sources = [os.path.basename(n) for n in sources] - with open(sbf_file, 'w') as f: - f.write("sources = {}\n".format(' '.join(sources))) - f.write("headers = {}\n".format(header)) - diff --git a/requirements/devel.txt b/requirements/devel.txt index 3332a7f7..23d99790 100644 --- a/requirements/devel.txt +++ b/requirements/devel.txt @@ -3,7 +3,7 @@ appdirs setuptools < 45 ; python_version < '3.0' setuptools ; python_version >= '3.0' -sip == 5.5.0 +sip == 6.6.2 wheel twine diff --git a/sip/siplib/LICENSE b/sip/siplib/LICENSE deleted file mode 100644 index 71567545..00000000 --- a/sip/siplib/LICENSE +++ /dev/null @@ -1,48 +0,0 @@ -RIVERBANK COMPUTING LIMITED LICENSE AGREEMENT FOR SIP - -1. This LICENSE AGREEMENT is between Riverbank Computing Limited ("Riverbank"), -and the Individual or Organization ("Licensee") accessing and otherwise using -SIP software in source or binary form and its associated documentation. SIP -comprises a software tool for generating Python bindings for software C and C++ -libraries, and a Python extension module used at runtime by those generated -bindings. - -2. Subject to the terms and conditions of this License Agreement, Riverbank -hereby grants Licensee a nonexclusive, royalty-free, world-wide license to -reproduce, analyze, test, perform and/or display publicly, prepare derivative -works, distribute, and otherwise use SIP alone or in any derivative version, -provided, however, that Riverbank's License Agreement and Riverbank's notice of -copyright, e.g., "Copyright (c) 2015 Riverbank Computing Limited; All Rights -Reserved" are retained in SIP alone or in any derivative version prepared by -Licensee. - -3. In the event Licensee prepares a derivative work that is based on or -incorporates SIP or any part thereof, and wants to make the derivative work -available to others as provided herein, then Licensee hereby agrees to include -in any such work a brief summary of the changes made to SIP. - -4. Licensee may not use SIP to generate Python bindings for any C or C++ -library for which bindings are already provided by Riverbank. - -5. Riverbank is making SIP available to Licensee on an "AS IS" basis. -RIVERBANK MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY -OF EXAMPLE, BUT NOT LIMITATION, RIVERBANK MAKES NO AND DISCLAIMS ANY -REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR -PURPOSE OR THAT THE USE OF SIP WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -6. RIVERBANK SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF SIP FOR ANY -INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, -DISTRIBUTING, OR OTHERWISE USING SIP, OR ANY DERIVATIVE THEREOF, EVEN IF -ADVISED OF THE POSSIBILITY THEREOF. - -7. This License Agreement will automatically terminate upon a material breach -of its terms and conditions. - -8. Nothing in this License Agreement shall be deemed to create any relationship -of agency, partnership, or joint venture between Riverbank and Licensee. This -License Agreement does not grant permission to use Riverbank trademarks or -trade name in a trademark sense to endorse or promote products or services of -Licensee, or any third party. - -9. By copying, installing or otherwise using SIP, Licensee agrees to be bound -by the terms and conditions of this License Agreement. diff --git a/sip/siplib/README.txt b/sip/siplib/README.txt deleted file mode 100644 index b745de83..00000000 --- a/sip/siplib/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -This folder contains a copy of the SIP runtime library code. It is -here so we can make it part of the wxPython build instead of needing -to have a dependency upon SIP already being installed on user -machines. - -3rd party extension modules that need to use or interact with wxPython -types or other items will need to ensure that they #include the sip.h -located in this folder so they will know the proper module name to -import to find this version of the runtime library. This feature was -added in SIP 4.12. - diff --git a/sip/siplib/apiversions.c b/sip/siplib/apiversions.c deleted file mode 100644 index 323a837a..00000000 --- a/sip/siplib/apiversions.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * The implementation of the support for setting API versions. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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 - -#include - -#include "sipint.h" - - -/* - * The structure that defines the version number of an API. - */ -typedef struct _apiVersionDef { - /* The name of the API. */ - const char *api_name; - - /* - * The version number of the API. This will either be set explicitly via - * a call to sip.setapi() or implicitly by an imported module. - */ - int version_nr; - - /* The next in the list of APIs. */ - struct _apiVersionDef *next; -} apiVersionDef; - - -/* - * The list of API versions. - */ -static apiVersionDef *api_versions = NULL; - - -/* - * Forward declarations. - */ -static int add_api(const char *api, int version_nr); -static apiVersionDef *find_api(const char *api); - - -/* - * See if a range of versions of a particular API is enabled. - */ -int sip_api_is_api_enabled(const char *name, int from, int to) -{ - const apiVersionDef *avd; - - if ((avd = find_api(name)) == NULL) - return FALSE; - - if (from > 0 && avd->version_nr < from) - return FALSE; - - if (to > 0 && avd->version_nr >= to) - return FALSE; - - return TRUE; -} - - -/* - * Initialise the the API for a module and return a negative value on error. - */ -int sipInitAPI(sipExportedModuleDef *em, PyObject *mod_dict) -{ - int *apis, i; - sipVersionedFunctionDef *vf; - sipTypeDef **tdp; - - /* See if the module defines any APIs. */ - if ((apis = em->em_versions) != NULL) - { - while (apis[0] >= 0) - { - /* - * See if it is an API definition rather than a range - * definition. - */ - if (apis[2] < 0) - { - const char *api_name; - const apiVersionDef *avd; - - api_name = sipNameFromPool(em, apis[0]); - - /* Use the default version if not already set explicitly. */ - if ((avd = find_api(api_name)) == NULL) - if (add_api(api_name, apis[1]) < 0) - return -1; - } - - apis += 3; - } - } - - /* Add any versioned global functions to the module dictionary. */ - if ((vf = em->em_versioned_functions) != NULL) - { - while (vf->vf_name >= 0) - { - if (sipIsRangeEnabled(em, vf->vf_api_range)) - { - const char *func_name = sipNameFromPool(em, vf->vf_name); - PyMethodDef *pmd; - PyObject *py_func; - - if ((pmd = sip_api_malloc(sizeof (PyMethodDef))) == NULL) - return -1; - - pmd->ml_name = func_name; - pmd->ml_meth = vf->vf_function; - pmd->ml_flags = vf->vf_flags; - pmd->ml_doc = vf->vf_docstring; - - if ((py_func = PyCFunction_New(pmd, NULL)) == NULL) - return -1; - - if (PyDict_SetItemString(mod_dict, func_name, py_func) < 0) - { - Py_DECREF(py_func); - return -1; - } - - Py_DECREF(py_func); - } - - ++vf; - } - } - - /* Update the types table according to any version information. */ - for (tdp = em->em_types, i = 0; i < em->em_nrtypes; ++i, ++tdp) - { - sipTypeDef *td; - - if ((td = *tdp) != NULL && td->td_version >= 0) - { - do - { - if (sipIsRangeEnabled(em, td->td_version)) - { - /* Update the type with the enabled version. */ - *tdp = td; - break; - } - } - while ((td = td->td_next_version) != NULL); - - /* - * If there is no enabled version then stub the disabled version - * so that we don't lose the name from the (sorted) types table. - */ - if (td == NULL) - sipTypeSetStub(*tdp); - } - } - - return 0; -} - - -/* - * Get the version number for an API. - */ -PyObject *sipGetAPI(PyObject *self, PyObject *args) -{ - const char *api; - const apiVersionDef *avd; - - (void)self; - - if (sip_api_deprecated(NULL, "getapi") < 0) - return NULL; - - if (!PyArg_ParseTuple(args, "s:getapi", &api)) - return NULL; - - if ((avd = find_api(api)) == NULL) - { - PyErr_Format(PyExc_ValueError, "unknown API '%s'", api); - return NULL; - } - - return PyLong_FromLong(avd->version_nr); -} - - -/* - * Set the version number for an API. - */ -PyObject *sipSetAPI(PyObject *self, PyObject *args) -{ - const char *api; - int version_nr; - const apiVersionDef *avd; - - (void)self; - - if (sip_api_deprecated(NULL, "setapi") < 0) - return NULL; - - if (!PyArg_ParseTuple(args, "si:setapi", &api, &version_nr)) - return NULL; - - if (version_nr < 1) - { - PyErr_Format(PyExc_ValueError, - "API version numbers must be greater or equal to 1, not %d", - version_nr); - return NULL; - } - - if ((avd = find_api(api)) == NULL) - { - char *api_copy; - - /* Make a deep copy of the name. */ - if ((api_copy = sip_api_malloc(strlen(api) + 1)) == NULL) - return NULL; - - strcpy(api_copy, api); - - if (add_api(api_copy, version_nr) < 0) - return NULL; - } - else if (avd->version_nr != version_nr) - { - PyErr_Format(PyExc_ValueError, - "API '%s' has already been set to version %d", api, - avd->version_nr); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Add a new API to the global list returning a negative value on error. - */ -static int add_api(const char *api, int version_nr) -{ - apiVersionDef *avd; - - if ((avd = sip_api_malloc(sizeof (apiVersionDef))) == NULL) - return -1; - - avd->api_name = api; - avd->version_nr = version_nr; - avd->next = api_versions; - - api_versions = avd; - - return 0; -} - - -/* - * Return the definition for the given API, or NULL if there was none. - */ -static apiVersionDef *find_api(const char *api) -{ - apiVersionDef *avd; - - for (avd = api_versions; avd != NULL; avd = avd->next) - if (strcmp(avd->api_name, api) == 0) - break; - - return avd; -} - - -/* - * Return TRUE if a range defined by a range index is enabled. - */ -int sipIsRangeEnabled(sipExportedModuleDef *em, int range_index) -{ - int *range = &em->em_versions[range_index * 3]; - const char *api_name = sipNameFromPool(em, range[0]); - - return sip_api_is_api_enabled(api_name, range[1], range[2]); -} diff --git a/sip/siplib/array.c b/sip/siplib/array.c deleted file mode 100644 index 5bb83a81..00000000 --- a/sip/siplib/array.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * This file implements the API for the array type. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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 - -#include -#include - -#include "sipint.h" - -#include "array.h" - - -/* The object data structure. */ -typedef struct { - PyObject_HEAD - void *data; - const sipTypeDef *td; - const char *format; - size_t stride; - Py_ssize_t len; - int flags; - PyObject *owner; -} sipArrayObject; - - -static int check_writable(sipArrayObject *array); -static int check_index(sipArrayObject *array, Py_ssize_t idx); -static void *get_value(sipArrayObject *array, PyObject *value); -static void *get_slice(sipArrayObject *array, PyObject *value, Py_ssize_t len); -static void bad_key(PyObject *key); -static void *element(sipArrayObject *array, Py_ssize_t idx); -static PyObject *make_array(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags, - PyObject *owner); - - -/* - * Implement len() for the type. - */ -static Py_ssize_t sipArray_length(PyObject *self) -{ - return ((sipArrayObject *)self)->len; -} - - -/* - * Implement sequence item sub-script for the type. - */ -static PyObject *sipArray_item(PyObject *self, Py_ssize_t idx) -{ - sipArrayObject *array = (sipArrayObject *)self; - PyObject *py_item; - void *data; - - if (check_index(array, idx) < 0) - return NULL; - - data = element(array, idx); - - if (array->td != NULL) - { - py_item = sip_api_convert_from_type(data, array->td, NULL); - } - else - { - switch (*array->format) - { - case 'b': - py_item = PyLong_FromLong(*(char *)data); - break; - - case 'B': - py_item = PyLong_FromUnsignedLong(*(unsigned char *)data); - break; - - case 'h': - py_item = PyLong_FromLong(*(short *)data); - break; - - case 'H': - py_item = PyLong_FromUnsignedLong(*(unsigned short *)data); - break; - - case 'i': - py_item = PyLong_FromLong(*(int *)data); - break; - - case 'I': - py_item = PyLong_FromUnsignedLong(*(unsigned int *)data); - break; - - case 'f': - py_item = PyFloat_FromDouble(*(float *)data); - break; - - case 'd': - py_item = PyFloat_FromDouble(*(double *)data); - break; - - default: - py_item = NULL; - } - } - - return py_item; -} - - -/* The sequence methods data structure. */ -static PySequenceMethods sipArray_SequenceMethods = { - sipArray_length, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - sipArray_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - - -/* - * Implement mapping sub-script for the type. - */ -static PyObject *sipArray_subscript(PyObject *self, PyObject *key) -{ - sipArrayObject *array = (sipArrayObject *)self; - - if (PyIndex_Check(key)) - { - Py_ssize_t idx = PyNumber_AsSsize_t(key, PyExc_IndexError); - - if (idx == -1 && PyErr_Occurred()) - return NULL; - - if (idx < 0) - idx += array->len; - - return sipArray_item(self, idx); - } - - if (PySlice_Check(key)) - { - Py_ssize_t start, stop, step, slicelength; - - if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &slicelength) < 0) - return NULL; - - if (step != 1) - { - PyErr_SetNone(PyExc_NotImplementedError); - return NULL; - } - - return make_array(element(array->data, start), array->td, - array->format, array->stride, slicelength, - (array->flags & ~SIP_OWNS_MEMORY), array->owner); - } - - bad_key(key); - - return NULL; -} - - -/* - * Implement mapping assignment sub-script for the type. - */ -static int sipArray_ass_subscript(PyObject *self, PyObject *key, - PyObject *value) -{ - sipArrayObject *array = (sipArrayObject *)self; - Py_ssize_t start, len; - void *value_data; - - if (check_writable(array) < 0) - return -1; - - if (PyIndex_Check(key)) - { - start = PyNumber_AsSsize_t(key, PyExc_IndexError); - - if (start == -1 && PyErr_Occurred()) - return -1; - - if (start < 0) - start += array->len; - - if (check_index(array, start) < 0) - return -1; - - if ((value_data = get_value(array, value)) == NULL) - return -1; - - len = 1; - } - else if (PySlice_Check(key)) - { - Py_ssize_t stop, step; - - if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &len) < 0) - return -1; - - if (step != 1) - { - PyErr_SetNone(PyExc_NotImplementedError); - return -1; - } - - if ((value_data = get_slice(array, value, len)) == NULL) - return -1; - } - else - { - bad_key(key); - - return -1; - } - - memmove(element(array, start), value_data, len * array->stride); - - return 0; -} - - -/* The mapping methods data structure. */ -static PyMappingMethods sipArray_MappingMethods = { - sipArray_length, /* mp_length */ - sipArray_subscript, /* mp_subscript */ - sipArray_ass_subscript, /* mp_ass_subscript */ -}; - - -/* - * The buffer implementation for Python v2.6.3 and later. - */ -static int sipArray_getbuffer(PyObject *self, Py_buffer *view, int flags) -{ - sipArrayObject *array = (sipArrayObject *)self; - - if (view == NULL) - return 0; - - if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) && (array->flags & SIP_READ_ONLY)) - { - PyErr_SetString(PyExc_BufferError, "object is not writable."); - return -1; - } - - view->obj = self; - Py_INCREF(self); - - view->buf = array->data; - view->len = array->len; - view->readonly = (array->flags & SIP_READ_ONLY); - view->itemsize = array->stride; - - view->format = NULL; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = (char *)array->format; - - view->ndim = 1; - - view->shape = NULL; - if ((flags & PyBUF_ND) == PyBUF_ND) - view->shape = &view->len; - - view->strides = NULL; - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) - view->strides = &view->itemsize; - - view->suboffsets = NULL; - view->internal = NULL; - - return 0; -} - - -/* The buffer methods data structure. */ -static PyBufferProcs sipArray_BufferProcs = { - sipArray_getbuffer, /* bf_getbuffer */ - 0 /* bf_releasebuffer */ -}; - - -/* The instance deallocation function. */ -static void sipArray_dealloc(PyObject *self) -{ - sipArrayObject *array = (sipArrayObject *)self; - - if (array->flags & SIP_OWNS_MEMORY) - sip_api_free(array->data); - else - Py_XDECREF(array->owner); -} - - -/* The type data structure. */ -PyTypeObject sipArray_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "sip.array", /* tp_name */ - sizeof (sipArrayObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - sipArray_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - &sipArray_SequenceMethods, /* tp_as_sequence */ - &sipArray_MappingMethods, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &sipArray_BufferProcs, /* tp_as_buffer */ -#if defined(Py_TPFLAGS_HAVE_NEWBUFFER) - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ -#endif - 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 */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* - * Check that an array is writable. - */ -static int check_writable(sipArrayObject *array) -{ - if (array->flags & SIP_READ_ONLY) - { - PyErr_SetString(PyExc_TypeError, "sip.array object is read-only"); - return -1; - } - - return 0; -} - - -/* - * Check that an index is valid for an array. - */ -static int check_index(sipArrayObject *array, Py_ssize_t idx) -{ - if (idx >= 0 && idx < array->len) - return 0; - - PyErr_SetString(PyExc_IndexError, "index out of bounds"); - - return -1; -} - - -/* - * Raise an exception about a bad sub-script key. - */ -static void bad_key(PyObject *key) -{ - PyErr_Format(PyExc_TypeError, - "cannot index a sip.array object using '%s'", - Py_TYPE(key)->tp_name); -} - - -/* - * Get the address of an element of an array. - */ -static void *element(sipArrayObject *array, Py_ssize_t idx) -{ - return (unsigned char *)(array->data) + idx * array->stride; -} - - -/* - * Get the address of a value that will be copied to an array. - */ -static void *get_value(sipArrayObject *array, PyObject *value) -{ - static union { - signed char s_char_t; - unsigned char u_char_t; - signed short s_short_t; - unsigned short u_short_t; - signed int s_int_t; - unsigned int u_int_t; - float float_t; - double double_t; - } static_data; - - void *data; - - if (array->td != NULL) - { - int iserr = FALSE; - - data = sip_api_force_convert_to_type(value, array->td, NULL, - SIP_NOT_NONE|SIP_NO_CONVERTORS, NULL, &iserr); - } - else - { - PyErr_Clear(); - - switch (*array->format) - { - case 'b': - static_data.s_char_t = sip_api_long_as_char(value); - data = &static_data.s_char_t; - break; - - case 'B': - static_data.u_char_t = sip_api_long_as_unsigned_char(value); - data = &static_data.u_char_t; - break; - - case 'h': - static_data.s_short_t = sip_api_long_as_short(value); - data = &static_data.s_short_t; - break; - - case 'H': - static_data.u_short_t = sip_api_long_as_unsigned_short(value); - data = &static_data.u_short_t; - break; - - case 'i': - static_data.s_int_t = sip_api_long_as_int(value); - data = &static_data.s_int_t; - break; - - case 'I': - static_data.u_int_t = sip_api_long_as_unsigned_int(value); - data = &static_data.u_int_t; - break; - - case 'f': - static_data.float_t = (float)PyFloat_AsDouble(value); - data = &static_data.float_t; - break; - - case 'd': - static_data.double_t = PyFloat_AsDouble(value); - data = &static_data.double_t; - break; - - default: - data = NULL; - } - - if (PyErr_Occurred()) - data = NULL; - } - - return data; -} - - -/* - * Get the address of an value that will be copied to an array slice. - */ -static void *get_slice(sipArrayObject *array, PyObject *value, Py_ssize_t len) -{ - sipArrayObject *other = (sipArrayObject *)value; - - if (!PyObject_IsInstance(value, (PyObject *)&sipArray_Type) || array->td != other->td || strcmp(array->format, other->format) != 0) - { - const char *type; - - if (array->td != NULL) - { - type = sipTypeName(array->td); - } - else - { - switch (*array->format) - { - case 'b': - type = "char"; - break; - - case 'B': - type = "unsigned char"; - break; - - case 'h': - type = "short"; - break; - - case 'H': - type = "unsigned short"; - break; - - case 'i': - type = "int"; - break; - - case 'I': - type = "unsigned int"; - break; - - case 'f': - type = "float"; - break; - - case 'd': - type = "double"; - break; - - default: - type = ""; - } - } - - PyErr_Format(PyExc_TypeError, - "can only assign another array of %s to the slice", type); - - return NULL; - } - - if (other->len != len) - { - PyErr_Format(PyExc_TypeError, - "the array being assigned must have length %zd", len); - - return NULL; - } - - if (other->stride == array->stride) - { - PyErr_Format(PyExc_TypeError, - "the array being assigned must have stride %zu", - array->stride); - - return NULL; - } - - return other->data; -} - - -/* - * Do the work of creating an array. - */ -static PyObject *make_array(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags, - PyObject *owner) -{ - sipArrayObject *array; - - if ((array = PyObject_NEW(sipArrayObject, &sipArray_Type)) == NULL) - return NULL; - - array->data = data; - array->td = td; - array->format = format; - array->stride = stride; - array->len = len; - array->flags = flags; - - if (flags & SIP_OWNS_MEMORY) - { - /* This is a borrowed reference to itself. */ - array->owner = (PyObject *)array; - } - else - { - Py_XINCREF(owner); - array->owner = owner; - } - - return (PyObject *)array; -} - - -/* - * Wrap an array of instances of a fundamental type. At the moment format must - * be either "b" (char), "B" (unsigned char), "h" (short), "H" (unsigned - * short), "i" (int), "I" (unsigned int), "f" (float) or "d" (double). - */ -PyObject *sip_api_convert_to_array(void *data, const char *format, - Py_ssize_t len, int flags) -{ - size_t stride; - - if (data == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - switch (*format) - { - case 'b': - stride = sizeof (char); - break; - - case 'B': - stride = sizeof (unsigned char); - break; - - case 'h': - stride = sizeof (short); - break; - - case 'H': - stride = sizeof (unsigned short); - break; - - case 'i': - stride = sizeof (int); - break; - - case 'I': - stride = sizeof (unsigned int); - break; - - case 'f': - stride = sizeof (float); - break; - - case 'd': - stride = sizeof (double); - break; - - default: - stride = 0; - } - - assert(stride > 0); - assert(len >= 0); - - return make_array(data, NULL, format, stride, len, flags, NULL); -} - - -/* - * Wrap an array of instances of a defined type. - */ -PyObject *sip_api_convert_to_typed_array(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags) -{ - if (data == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - assert(stride > 0); - assert(len >= 0); - - return make_array(data, td, format, stride, len, flags, NULL); -} diff --git a/sip/siplib/array.h b/sip/siplib/array.h deleted file mode 100644 index fbe5525d..00000000 --- a/sip/siplib/array.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file defines the API for the array type. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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. - */ - - -#ifndef _ARRAY_H -#define _ARRAY_H - - -#include - -#include "sipint.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -extern PyTypeObject sipArray_Type; - -PyObject *sip_api_convert_to_array(void *data, const char *format, - Py_ssize_t len, int flags); -PyObject *sip_api_convert_to_typed_array(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/sip/siplib/bool.cpp b/sip/siplib/bool.cpp deleted file mode 100644 index 781babbf..00000000 --- a/sip/siplib/bool.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This contains all the C++ code that is needed by the sip module. -// -// Copyright (c) 2015 Riverbank Computing Limited -// -// 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. - - -// Set a C++ bool for the main C implementation of the module. -extern "C" void sipSetBool(void *ptr, int val) -{ - *reinterpret_cast(ptr) = !!val; -} diff --git a/sip/siplib/descriptors.c b/sip/siplib/descriptors.c deleted file mode 100644 index 06bc53f3..00000000 --- a/sip/siplib/descriptors.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * The implementation of the different descriptors. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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 - -#include "sipint.h" - - -/***************************************************************************** - * A method descriptor. We don't use the similar Python descriptor because it - * doesn't support a method having static and non-static overloads, and we - * handle mixins via a delegate. - *****************************************************************************/ - - -/* Forward declarations of slots. */ -static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj, - PyObject *type); -static PyObject *sipMethodDescr_repr(PyObject *self); -static int sipMethodDescr_traverse(PyObject *self, visitproc visit, void *arg); -static int sipMethodDescr_clear(PyObject *self); -static void sipMethodDescr_dealloc(PyObject *self); - - -/* - * The object data structure. - */ -typedef struct _sipMethodDescr { - PyObject_HEAD - - /* The method definition. */ - PyMethodDef *pmd; - - /* The mixin name, if any. */ - PyObject *mixin_name; -} sipMethodDescr; - - -/* - * The type data structure. - */ -PyTypeObject sipMethodDescr_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "sip.methoddescriptor", /* tp_name */ - sizeof (sipMethodDescr), /* tp_basicsize */ - 0, /* tp_itemsize */ - sipMethodDescr_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - sipMethodDescr_repr, /* 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_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - sipMethodDescr_traverse,/* tp_traverse */ - sipMethodDescr_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 */ - sipMethodDescr_descr_get, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* - * Return a new method descriptor for the given method. - */ -PyObject *sipMethodDescr_New(PyMethodDef *pmd) -{ - PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0); - - if (descr != NULL) - { - ((sipMethodDescr *)descr)->pmd = pmd; - ((sipMethodDescr *)descr)->mixin_name = NULL; - } - - return descr; -} - - -/* - * Return a new method descriptor based on an existing one and a mixin name. - */ -PyObject *sipMethodDescr_Copy(PyObject *orig, PyObject *mixin_name) -{ - PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0); - - if (descr != NULL) - { - ((sipMethodDescr *)descr)->pmd = ((sipMethodDescr *)orig)->pmd; - ((sipMethodDescr *)descr)->mixin_name = mixin_name; - Py_INCREF(mixin_name); - } - - return descr; -} - - -/* - * The descriptor's descriptor get slot. - */ -static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj, - PyObject *type) -{ - sipMethodDescr *md = (sipMethodDescr *)self; - - (void)type; - - if (obj == Py_None) - obj = NULL; - else if (md->mixin_name != NULL) - obj = PyObject_GetAttr(obj, md->mixin_name); - - return PyCFunction_New(md->pmd, obj); -} - - -/* - * The descriptor's repr slot. This is for the benefit of cProfile which seems - * to determine attribute names differently to the rest of Python. - */ -static PyObject *sipMethodDescr_repr(PyObject *self) -{ - sipMethodDescr *md = (sipMethodDescr *)self; - - return PyUnicode_FromFormat("", md->pmd->ml_name); -} - - -/* - * The descriptor's traverse slot. - */ -static int sipMethodDescr_traverse(PyObject *self, visitproc visit, void *arg) -{ - if (((sipMethodDescr *)self)->mixin_name != NULL) - { - int vret = visit(((sipMethodDescr *)self)->mixin_name, arg); - - if (vret != 0) - return vret; - } - - return 0; -} - - -/* - * The descriptor's clear slot. - */ -static int sipMethodDescr_clear(PyObject *self) -{ - PyObject *tmp = ((sipMethodDescr *)self)->mixin_name; - - ((sipMethodDescr *)self)->mixin_name = NULL; - Py_XDECREF(tmp); - - return 0; -} - - -/* - * The descriptor's dealloc slot. - */ -static void sipMethodDescr_dealloc(PyObject *self) -{ - sipMethodDescr_clear(self); - Py_TYPE(self)->tp_free(self); -} - - -/***************************************************************************** - * A variable descriptor. We don't use the similar Python descriptor because - * it doesn't support static variables. - *****************************************************************************/ - - -/* Forward declarations of slots. */ -static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj, - PyObject *type); -static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj, - PyObject *value); -static int sipVariableDescr_traverse(PyObject *self, visitproc visit, - void *arg); -static int sipVariableDescr_clear(PyObject *self); -static void sipVariableDescr_dealloc(PyObject *self); - - -/* - * The object data structure. - */ -typedef struct _sipVariableDescr { - PyObject_HEAD - - /* The getter/setter definition. */ - sipVariableDef *vd; - - /* The generated type definition. */ - const sipTypeDef *td; - - /* The generated container definition. */ - const sipContainerDef *cod; - - /* The mixin name, if any. */ - PyObject *mixin_name; -} sipVariableDescr; - - -/* - * The type data structure. - */ -PyTypeObject sipVariableDescr_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "sip.variabledescriptor", /* tp_name */ - sizeof (sipVariableDescr), /* tp_basicsize */ - 0, /* tp_itemsize */ - sipVariableDescr_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 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_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - sipVariableDescr_traverse, /* tp_traverse */ - sipVariableDescr_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 */ - sipVariableDescr_descr_get, /* tp_descr_get */ - sipVariableDescr_descr_set, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* Forward declarations. */ -static int get_instance_address(sipVariableDescr *vd, PyObject *obj, - void **addrp); - - -/* - * Return a new method descriptor for the given getter/setter. - */ -PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td, - const sipContainerDef *cod) -{ - PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0); - - if (descr != NULL) - { - ((sipVariableDescr *)descr)->vd = vd; - ((sipVariableDescr *)descr)->td = td; - ((sipVariableDescr *)descr)->cod = cod; - ((sipVariableDescr *)descr)->mixin_name = NULL; - } - - return descr; -} - - -/* - * Return a new variable descriptor based on an existing one and a mixin name. - */ -PyObject *sipVariableDescr_Copy(PyObject *orig, PyObject *mixin_name) -{ - PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0); - - if (descr != NULL) - { - ((sipVariableDescr *)descr)->vd = ((sipVariableDescr *)orig)->vd; - ((sipVariableDescr *)descr)->td = ((sipVariableDescr *)orig)->td; - ((sipVariableDescr *)descr)->cod = ((sipVariableDescr *)orig)->cod; - ((sipVariableDescr *)descr)->mixin_name = mixin_name; - Py_INCREF(mixin_name); - } - - return descr; -} - - -/* - * The descriptor's descriptor get slot. - */ -static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj, - PyObject *type) -{ - sipVariableDescr *vd = (sipVariableDescr *)self; - void *addr; - - if (get_instance_address(vd, obj, &addr) < 0) - return NULL; - - return ((sipVariableGetterFunc)vd->vd->vd_getter)(addr, obj, type); -} - - -/* - * The descriptor's descriptor set slot. - */ -static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj, - PyObject *value) -{ - sipVariableDescr *vd = (sipVariableDescr *)self; - void *addr; - - /* Check that the value isn't const. */ - if (vd->vd->vd_setter == NULL) - { - PyErr_Format(PyExc_AttributeError, - "'%s' object attribute '%s' is read-only", - sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name); - - return -1; - } - - if (get_instance_address(vd, obj, &addr) < 0) - return -1; - - return ((sipVariableSetterFunc)vd->vd->vd_setter)(addr, value, obj); -} - - -/* - * Return the C/C++ address of any instance. - */ -static int get_instance_address(sipVariableDescr *vd, PyObject *obj, - void **addrp) -{ - void *addr; - - if (vd->vd->vd_type == ClassVariable) - { - addr = NULL; - } - else - { - /* Check that access was via an instance. */ - if (obj == NULL || obj == Py_None) - { - PyErr_Format(PyExc_AttributeError, - "'%s' object attribute '%s' is an instance attribute", - sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name); - - return -1; - } - - if (vd->mixin_name != NULL) - obj = PyObject_GetAttr(obj, vd->mixin_name); - - /* Get the C++ instance. */ - if ((addr = sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, vd->td)) == NULL) - return -1; - } - - *addrp = addr; - - return 0; -} - - -/* - * The descriptor's traverse slot. - */ -static int sipVariableDescr_traverse(PyObject *self, visitproc visit, void *arg) -{ - if (((sipVariableDescr *)self)->mixin_name != NULL) - { - int vret = visit(((sipVariableDescr *)self)->mixin_name, arg); - - if (vret != 0) - return vret; - } - - return 0; -} - - -/* - * The descriptor's clear slot. - */ -static int sipVariableDescr_clear(PyObject *self) -{ - PyObject *tmp = ((sipVariableDescr *)self)->mixin_name; - - ((sipVariableDescr *)self)->mixin_name = NULL; - Py_XDECREF(tmp); - - return 0; -} - - -/* - * The descriptor's dealloc slot. - */ -static void sipVariableDescr_dealloc(PyObject *self) -{ - sipVariableDescr_clear(self); - Py_TYPE(self)->tp_free(self); -} diff --git a/sip/siplib/int_convertors.c b/sip/siplib/int_convertors.c deleted file mode 100644 index cedcc954..00000000 --- a/sip/siplib/int_convertors.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * The implementation of the Python object to C/C++ integer converters. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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. - */ - - -/* - * NOTES - * - * The legacy integer conversions (ie. without support for overflow checking) - * are flawed and inconsistent. Large Python signed values were converted to - * -1 whereas small values were truncated. When converting function arguments - * all overlows were ignored, however when converting the results returned by - * Python re-implementations then large Python values raised an exception - * whereas small values were truncated. - * - * With the new integer conversions large Python signed values will always - * raise an overflow exception (even if overflow checking is disabled). This - * is because a truncated value is not available - it would have to be - * computed. This may cause new exceptions to be raised but is justified in - * that the value that was being used bore no relation to the original value. - */ - - -#include - -#include - -#include "sipint.h" - - -/* Wrappers to deal with lack of long long support. */ -#if defined(HAVE_LONG_LONG) -#define SIPLong_AsLongLong PyLong_AsLongLong -#define SIP_LONG_LONG PY_LONG_LONG -#define SIP_LONG_LONG_FORMAT "%lld" -#define SIP_UNSIGNED_LONG_LONG_FORMAT "%llu" -#else -#define SIPLong_AsLongLong PyLong_AsLong -#define SIP_LONG_LONG long -#define SIP_LONG_LONG_FORMAT "%ld" -#define SIP_UNSIGNED_LONG_LONG_FORMAT "%lu" -#endif - - -static int overflow_checking = FALSE; /* Check for overflows. */ - -static SIP_LONG_LONG long_as_long_long(PyObject *o, SIP_LONG_LONG min, - SIP_LONG_LONG max); -static unsigned long long_as_unsigned_long(PyObject *o, unsigned long max); -static void raise_signed_overflow(SIP_LONG_LONG min, SIP_LONG_LONG max); -static void raise_unsigned_overflow(unsigned SIP_LONG_LONG max); - - -/* - * Enable or disable overflow checking (Python API). - */ -PyObject *sipEnableOverflowChecking(PyObject *self, PyObject *args) -{ - int enable; - - (void)self; - - if (PyArg_ParseTuple(args, "i:enableoverflowchecking", &enable)) - { - PyObject *res; - - res = (sip_api_enable_overflow_checking(enable) ? Py_True : Py_False); - - Py_INCREF(res); - return res; - } - - return NULL; -} - - -/* - * Enable or disable overflow checking (C API). - */ -int sip_api_enable_overflow_checking(int enable) -{ - int was_enabled = overflow_checking; - - overflow_checking = enable; - - return was_enabled; -} - - -/* - * Convert a Python object to a C++ bool (returned as an int). - */ -int sip_api_convert_to_bool(PyObject *o) -{ - int was_enabled, v; - - /* Convert the object to an int while checking for overflow. */ - was_enabled = sip_api_enable_overflow_checking(TRUE); - v = sip_api_long_as_int(o); - sip_api_enable_overflow_checking(was_enabled); - - if (PyErr_Occurred()) - { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - { - PyErr_Clear(); - - /* The value must have been non-zero. */ - v = 1; - } - else - { - PyErr_Format(PyExc_TypeError, "a 'bool' is expected not '%s'", - Py_TYPE(o)->tp_name); - - v = -1; - } - } - else if (v != 0) - { - v = 1; - } - - return v; -} - - -/* - * Convert a Python object to a C char. - */ -char sip_api_long_as_char(PyObject *o) -{ - return (char)long_as_long_long(o, CHAR_MIN, CHAR_MAX); -} - - -/* - * Convert a Python object to a C signed char. - */ -signed char sip_api_long_as_signed_char(PyObject *o) -{ - return (signed char)long_as_long_long(o, SCHAR_MIN, SCHAR_MAX); -} - - -/* - * Convert a Python object to a C unsigned char. - */ -unsigned char sip_api_long_as_unsigned_char(PyObject *o) -{ - return (unsigned char)long_as_unsigned_long(o, UCHAR_MAX); -} - - -/* - * Convert a Python object to a C short. - */ -short sip_api_long_as_short(PyObject *o) -{ - return (short)long_as_long_long(o, SHRT_MIN, SHRT_MAX); -} - - -/* - * Convert a Python object to a C unsigned short. - */ -unsigned short sip_api_long_as_unsigned_short(PyObject *o) -{ - return (unsigned short)long_as_unsigned_long(o, USHRT_MAX); -} - - -/* - * Convert a Python object to a C int. - */ -int sip_api_long_as_int(PyObject *o) -{ - return (int)long_as_long_long(o, INT_MIN, INT_MAX); -} - - -/* - * Convert a Python object to a C unsigned int. - */ -unsigned sip_api_long_as_unsigned_int(PyObject *o) -{ - return (unsigned)long_as_unsigned_long(o, UINT_MAX); -} - - -/* - * Convert a Python object to a C size_t. - */ -size_t sip_api_long_as_size_t(PyObject *o) -{ - return (size_t)long_as_unsigned_long(o, SIZE_MAX); -} - - -/* - * Convert a Python object to a C long. - */ -long sip_api_long_as_long(PyObject *o) -{ - return (long)long_as_long_long(o, LONG_MIN, LONG_MAX); -} - - -/* - * Convert a Python object to a C unsigned long. - */ -unsigned long sip_api_long_as_unsigned_long(PyObject *o) -{ - return long_as_unsigned_long(o, ULONG_MAX); -} - - -#if defined(HAVE_LONG_LONG) -/* - * Convert a Python object to a C long long. - */ -PY_LONG_LONG sip_api_long_as_long_long(PyObject *o) -{ - return long_as_long_long(o, LLONG_MIN, LLONG_MAX); -} - - -/* - * Convert a Python object to a C unsigned long long. - */ -unsigned PY_LONG_LONG sip_api_long_as_unsigned_long_long(PyObject *o) -{ - unsigned PY_LONG_LONG value; - - /* - * Note that this doesn't handle Python v2 int objects, but the old - * converters didn't either. - */ - - PyErr_Clear(); - - if (overflow_checking) - { - value = PyLong_AsUnsignedLongLong(o); - - if (PyErr_Occurred()) - { - /* Provide a better exception message. */ - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - raise_unsigned_overflow(ULLONG_MAX); - } - } - else - { - value = PyLong_AsUnsignedLongLongMask(o); - } - - return value; -} -#endif - - -/* - * Convert a Python object to a long long checking that the value is within a - * range if overflow checking is enabled. - */ -static SIP_LONG_LONG long_as_long_long(PyObject *o, SIP_LONG_LONG min, - SIP_LONG_LONG max) -{ - SIP_LONG_LONG value; - - PyErr_Clear(); - - value = SIPLong_AsLongLong(o); - - if (PyErr_Occurred()) - { - /* Provide a better exception message. */ - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - raise_signed_overflow(min, max); - } - else if (overflow_checking && (value < min || value > max)) - { - raise_signed_overflow(min, max); - } - - return value; -} - - -/* - * Convert a Python object to an unsigned long checking that the value is - * within a range if overflow checking is enabled. - */ -static unsigned long long_as_unsigned_long(PyObject *o, unsigned long max) -{ - unsigned long value; - - PyErr_Clear(); - - if (overflow_checking) - { - value = PyLong_AsUnsignedLong(o); - - if (PyErr_Occurred()) - { - /* Provide a better exception message. */ - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - raise_unsigned_overflow(max); - } - else if (value > max) - { - raise_unsigned_overflow(max); - } - } - else - { - value = PyLong_AsUnsignedLongMask(o); - } - - return value; -} - - -/* - * Raise an overflow exception if a signed value is out of range. - */ -static void raise_signed_overflow(SIP_LONG_LONG min, SIP_LONG_LONG max) -{ - PyErr_Format(PyExc_OverflowError, - "value must be in the range " SIP_LONG_LONG_FORMAT " to " SIP_LONG_LONG_FORMAT, - min, max); -} - - -/* - * Raise an overflow exception if an unsigned value is out of range. - */ -static void raise_unsigned_overflow(unsigned SIP_LONG_LONG max) -{ - PyErr_Format(PyExc_OverflowError, - "value must be in the range 0 to " SIP_UNSIGNED_LONG_LONG_FORMAT, - max); -} diff --git a/sip/siplib/objmap.c b/sip/siplib/objmap.c deleted file mode 100644 index 989817b8..00000000 --- a/sip/siplib/objmap.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * This module implements a hash table class for mapping C/C++ addresses to the - * corresponding wrapped Python object. - * - * Copyright (c) 2017 Riverbank Computing Limited - * - * 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 - -#include "sipint.h" - - -#define hash_1(k,s) (((unsigned long)(k)) % (s)) -#define hash_2(k,s) ((s) - 2 - (hash_1((k),(s)) % ((s) - 2))) - - -/* Prime numbers to use as hash table sizes. */ -static unsigned long hash_primes[] = { - 521, 1031, 2053, 4099, - 8209, 16411, 32771, 65537, 131101, 262147, - 524309, 1048583, 2097169, 4194319, 8388617, 16777259, - 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827, - 2147483659U,0 -}; - - -static sipHashEntry *newHashTable(unsigned long); -static sipHashEntry *findHashEntry(sipObjectMap *,void *); -static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); -static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, - const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); -static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); -static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, - const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); -static void reorganiseMap(sipObjectMap *om); -static void *getUnguardedPointer(sipSimpleWrapper *w); - - -/* - * Initialise an object map. - */ -void sipOMInit(sipObjectMap *om) -{ - om -> primeIdx = 0; - om -> unused = om -> size = hash_primes[om -> primeIdx]; - om -> stale = 0; - om -> hash_array = newHashTable(om -> size); -} - - -/* - * Finalise an object map. - */ -void sipOMFinalise(sipObjectMap *om) -{ - sip_api_free(om -> hash_array); -} - - -/* - * Allocate and initialise a new hash table. - */ -static sipHashEntry *newHashTable(unsigned long size) -{ - size_t nbytes; - sipHashEntry *hashtab; - - nbytes = sizeof (sipHashEntry) * size; - - if ((hashtab = (sipHashEntry *)sip_api_malloc(nbytes)) != NULL) - memset(hashtab,0,nbytes); - - return hashtab; -} - - -/* - * Return a pointer to the hash entry that is used, or should be used, for the - * given C/C++ address. - */ -static sipHashEntry *findHashEntry(sipObjectMap *om,void *key) -{ - unsigned long hash, inc; - void *hek; - - hash = hash_1(key,om -> size); - inc = hash_2(key,om -> size); - - while ((hek = om -> hash_array[hash].key) != NULL && hek != key) - hash = (hash + inc) % om -> size; - - return &om -> hash_array[hash]; -} - - -/* - * Return the wrapped Python object of a specific type for a C/C++ address or - * NULL if it wasn't found. - */ -sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, - const sipTypeDef *td) -{ - sipHashEntry *he = findHashEntry(om, key); - sipSimpleWrapper *sw; - PyTypeObject *py_type = sipTypeAsPyTypeObject(td); - - /* Go through each wrapped object at this address. */ - for (sw = he->first; sw != NULL; sw = sw->next) - { - sipSimpleWrapper *unaliased; - - unaliased = (sipIsAlias(sw) ? (sipSimpleWrapper *)sw->data : sw); - - /* - * If the reference count is 0 then it is in the process of being - * deleted, so ignore it. It's not completely clear how this can - * happen (but it can) because it implies that the garbage collection - * code is being re-entered (and there are guards in place to prevent - * this). - */ - if (Py_REFCNT(unaliased) == 0) - continue; - - /* Ignore it if the C/C++ address is no longer valid. */ - if (sip_api_get_address(unaliased) == NULL) - continue; - - /* - * If this wrapped object is of the given type, or a sub-type of it, - * then we assume it is the same C++ object. - */ - if (PyObject_TypeCheck(unaliased, py_type)) - return unaliased; - } - - return NULL; -} - - -/* - * Add a C/C++ address and the corresponding wrapped Python object to the map. - */ -void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val) -{ - void *addr = getUnguardedPointer(val); - const sipClassTypeDef *base_ctd; - - /* Add the object. */ - add_object(om, addr, val); - - /* Add any aliases. */ - base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->wt_td; - add_aliases(om, addr, val, base_ctd, base_ctd); -} - - -/* - * Add an alias for any address that is different when cast to a super-type. - */ -static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, - const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) -{ - const sipEncodedTypeDef *sup; - - /* See if there are any super-classes. */ - if ((sup = ctd->ctd_supers) != NULL) - { - sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); - - /* Recurse up the hierarchy for the first super-class. */ - add_aliases(om, addr, val, base_ctd, sup_ctd); - - /* - * We only check for aliases for subsequent super-classes because the - * first one can never need one. - */ - while (!sup++->sc_flag) - { - void *sup_addr; - - sup_ctd = sipGetGeneratedClassType(sup, ctd); - - /* Recurse up the hierarchy for the remaining super-classes. */ - add_aliases(om, addr, val, base_ctd, sup_ctd); - - sup_addr = (*base_ctd->ctd_cast)(addr, (sipTypeDef *)sup_ctd); - - if (sup_addr != addr) - { - sipSimpleWrapper *alias; - - /* Note that we silently ignore errors. */ - if ((alias = sip_api_malloc(sizeof (sipSimpleWrapper))) != NULL) - { - /* - * An alias is basically a bit-wise copy of the Python - * object but only to ensure the fields we are subverting - * are in the right place. An alias should never be passed - * to the Python API. - */ - *alias = *val; - - alias->sw_flags = (val->sw_flags & SIP_SHARE_MAP) | SIP_ALIAS; - alias->data = val; - alias->next = NULL; - - add_object(om, sup_addr, alias); - } - } - } - } -} - - -/* - * Add a wrapper (which may be an alias) to the map. - */ -static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) -{ - sipHashEntry *he = findHashEntry(om, addr); - - /* - * If the bucket is in use then we appear to have several objects at the - * same address. - */ - if (he->first != NULL) - { - /* - * This can happen for three reasons. A variable of one class can be - * declared at the start of another class. Therefore there are two - * objects, of different classes, with the same address. The second - * reason is that the old C/C++ object has been deleted by C/C++ but we - * didn't get to find out for some reason, and a new C/C++ instance has - * been created at the same address. The third reason is if we are in - * the process of deleting a Python object but the C++ object gets - * wrapped again because the C++ dtor called a method that has been - * re-implemented in Python. The absence of the SIP_SHARE_MAP flag - * tells us that a new C++ instance has just been created and so we - * know the second reason is the correct one so we mark the old - * pointers as invalid and reuse the entry. Otherwise we just add this - * one to the existing list of objects at this address. - */ - if (!(val->sw_flags & SIP_SHARE_MAP)) - { - sipSimpleWrapper *sw = he->first; - - he->first = NULL; - - while (sw != NULL) - { - sipSimpleWrapper *next = sw->next; - - if (sipIsAlias(sw)) - { - sip_api_free(sw); - } - else - { - /* - * We are removing it from the map here. However, note - * that we first have to call the destructor before marking - * it as not being in the map, as the destructor itself - * might end up trying to remove the wrapper and its - * aliases from the map. In that case, if the wrapper is - * already marked as not in the map, the removal will just - * return early, leaving any potential aliases as stale - * entries in the map. If we later try to wrap a different - * object at the same address, we end up retrieving the - * stale alias entry from the object map, triggering a - * use-after-free when accessing its C++ object. - */ - sip_api_instance_destroyed(sw); - sipSetNotInMap(sw); - } - - sw = next; - } - } - - val->next = he->first; - he->first = val; - - return; - } - - /* See if the bucket was unused or stale. */ - if (he->key == NULL) - { - he->key = addr; - om->unused--; - } - else - { - om->stale--; - } - - /* Add the rest of the new value. */ - he->first = val; - val->next = NULL; - - reorganiseMap(om); -} - - -/* - * Reorganise a map if it is running short of space. - */ -static void reorganiseMap(sipObjectMap *om) -{ - unsigned long old_size, i; - sipHashEntry *ohe, *old_tab; - - /* Don't bother if it still has more than 12% available. */ - if (om -> unused > om -> size >> 3) - return; - - /* - * If reorganising (ie. making the stale buckets unused) using the same - * sized table would make 25% available then do that. Otherwise use a - * bigger table (if possible). - */ - if (om -> unused + om -> stale < om -> size >> 2 && hash_primes[om -> primeIdx + 1] != 0) - om -> primeIdx++; - - old_size = om -> size; - old_tab = om -> hash_array; - - om -> unused = om -> size = hash_primes[om -> primeIdx]; - om -> stale = 0; - om -> hash_array = newHashTable(om -> size); - - /* Transfer the entries from the old table to the new one. */ - ohe = old_tab; - - for (i = 0; i < old_size; ++i) - { - if (ohe -> key != NULL && ohe -> first != NULL) - { - *findHashEntry(om,ohe -> key) = *ohe; - om -> unused--; - } - - ++ohe; - } - - sip_api_free(old_tab); -} - - -/* - * Remove a C/C++ object from the table. Return 0 if it was removed - * successfully. - */ -int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val) -{ - void *addr; - const sipClassTypeDef *base_ctd; - - /* Handle the trivial case. */ - if (sipNotInMap(val)) - return 0; - - if ((addr = getUnguardedPointer(val)) == NULL) - return 0; - - /* Remove any aliases. */ - base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->wt_td; - remove_aliases(om, addr, val, base_ctd, base_ctd); - - /* Remove the object. */ - return remove_object(om, addr, val); -} - - -/* - * Remove an alias for any address that is different when cast to a super-type. - */ -static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, - const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) -{ - const sipEncodedTypeDef *sup; - - /* See if there are any super-classes. */ - if ((sup = ctd->ctd_supers) != NULL) - { - sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); - - /* Recurse up the hierarchy for the first super-class. */ - remove_aliases(om, addr, val, base_ctd, sup_ctd); - - /* - * We only check for aliases for subsequent super-classes because the - * first one can never need one. - */ - while (!sup++->sc_flag) - { - void *sup_addr; - - sup_ctd = sipGetGeneratedClassType(sup, ctd); - - /* Recurse up the hierarchy for the remaining super-classes. */ - remove_aliases(om, addr, val, base_ctd, sup_ctd); - - sup_addr = (*base_ctd->ctd_cast)(addr, (sipTypeDef *)sup_ctd); - - if (sup_addr != addr) - remove_object(om, sup_addr, val); - } - } -} - - -/* - * Remove a wrapper from the map. - */ -static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) -{ - sipHashEntry *he = findHashEntry(om, addr); - sipSimpleWrapper **swp; - - for (swp = &he->first; *swp != NULL; swp = &(*swp)->next) - { - sipSimpleWrapper *sw, *next; - int do_remove; - - sw = *swp; - next = sw->next; - - if (sipIsAlias(sw)) - { - if (sw->data == val) - { - sip_api_free(sw); - do_remove = TRUE; - } - else - { - do_remove = FALSE; - } - } - else - { - do_remove = (sw == val); - } - - if (do_remove) - { - *swp = next; - - /* - * If the bucket is now empty then count it as stale. Note that we - * do not NULL the key and count it as unused because that might - * throw out the search for another entry that wanted to go here, - * found it already occupied, and was put somewhere else. In other - * words, searches must be repeatable until we reorganise the - * table. - */ - if (he->first == NULL) - om->stale++; - - return 0; - } - } - - return -1; -} - - -/* - * Return the unguarded pointer to a C/C++ instance, ie. the pointer was valid - * but may longer be. - */ -static void *getUnguardedPointer(sipSimpleWrapper *w) -{ - return (w->access_func != NULL) ? w->access_func(w, UnguardedPointer) : w->data; -} diff --git a/sip/siplib/qtlib.c b/sip/siplib/qtlib.c deleted file mode 100644 index dc457adf..00000000 --- a/sip/siplib/qtlib.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * The SIP library code that implements the interface to the optional module - * supplied Qt support. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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 -#include -#include - -#include "sipint.h" - - -/* This is how Qt "types" signals and slots. */ -#define isQtSlot(s) (*(s) == '1') -#define isQtSignal(s) (*(s) == '2') - - -static PyObject *getWeakRef(PyObject *obj); -static char *sipStrdup(const char *); -static void *createUniversalSlot(sipWrapper *txSelf, const char *sig, - PyObject *rxObj, const char *slot, const char **member, int flags); -static void *findSignal(void *txrx, const char **sig); -static void *newSignal(void *txrx, const char **sig); - - -/* - * Find an existing signal. - */ -static void *findSignal(void *txrx, const char **sig) -{ - if (sipQtSupport->qt_find_universal_signal != NULL) - txrx = sipQtSupport->qt_find_universal_signal(txrx, sig); - - return txrx; -} - - -/* - * Return a usable signal, creating a new universal signal if needed. - */ -static void *newSignal(void *txrx, const char **sig) -{ - void *new_txrx = findSignal(txrx, sig); - - if (new_txrx == NULL && sipQtSupport->qt_create_universal_signal != NULL) - new_txrx = sipQtSupport->qt_create_universal_signal(txrx, sig); - - return new_txrx; -} - - -/* - * Create a universal slot. Returns a pointer to it or 0 if there was an - * error. - */ -static void *createUniversalSlot(sipWrapper *txSelf, const char *sig, - PyObject *rxObj, const char *slot, const char **member, int flags) -{ - void *us; - - assert(sipQtSupport->qt_create_universal_slot); - - us = sipQtSupport->qt_create_universal_slot(txSelf, sig, rxObj, slot, - member, flags); - - if (us && txSelf) - sipSetPossibleProxy((sipSimpleWrapper *)txSelf); - - return us; -} - - -/* - * Invoke a single slot (Qt or Python) and return the result. Don't check if - * any receiver C++ object still exists. - */ -PyObject *sip_api_invoke_slot(const sipSlot *slot, PyObject *sigargs) -{ - return sip_api_invoke_slot_ex(slot, sigargs, TRUE); -} - - -/* - * Invoke a single slot (Qt or Python) and return the result. Optionally check - * that any receiver C++ object still exist. - */ -PyObject *sip_api_invoke_slot_ex(const sipSlot *slot, PyObject *sigargs, - int no_receiver_check) -{ - PyObject *sa, *oxtype, *oxvalue, *oxtb, *sfunc, *sref; - - assert(sipQtSupport); - - /* Keep some compilers quiet. */ - oxtype = oxvalue = oxtb = NULL; - - /* Fan out Qt signals. (Only PyQt3 would do this.) */ - if (slot->name != NULL && slot->name[0] != '\0') - { - assert(sipQtSupport->qt_emit_signal); - - if (sipQtSupport->qt_emit_signal(slot->pyobj, slot->name, sigargs) < 0) - return NULL; - - Py_INCREF(Py_None); - return Py_None; - } - - /* Get the object to call, resolving any weak references. */ - if (slot->weakSlot == Py_True) - { - /* - * The slot is guaranteed to be Ok because it has an extra reference or - * is None. - */ - sref = slot->pyobj; - Py_INCREF(sref); - } - else if (slot -> weakSlot == NULL) - sref = NULL; - else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL) - return NULL; - else - Py_INCREF(sref); - - if (sref == Py_None) - { - /* - * If the real object has gone then we pretend everything is Ok. This - * mimics the Qt behaviour of not caring if a receiving object has been - * deleted. - */ - Py_DECREF(sref); - - Py_INCREF(Py_None); - return Py_None; - } - - if (slot -> pyobj == NULL) - { - PyObject *self = (sref != NULL ? sref : slot->meth.mself); - - /* - * If the receiver wraps a C++ object then ignore the call if it no - * longer exists. - */ - if (!no_receiver_check && - PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type) && - sip_api_get_address((sipSimpleWrapper *)self) == NULL) - { - Py_XDECREF(sref); - - Py_INCREF(Py_None); - return Py_None; - } - - if ((sfunc = PyMethod_New(slot->meth.mfunc, self)) == NULL) - { - Py_XDECREF(sref); - return NULL; - } - } - else if (slot -> name != NULL) - { - char *mname = slot -> name + 1; - PyObject *self = (sref != NULL ? sref : slot->pyobj); - - if ((sfunc = PyObject_GetAttrString(self, mname)) == NULL || !PyCFunction_Check(sfunc)) - { - /* - * Note that in earlier versions of SIP this error would be - * detected when the slot was connected. - */ - PyErr_Format(PyExc_NameError,"Invalid slot %s",mname); - - Py_XDECREF(sfunc); - Py_XDECREF(sref); - return NULL; - } - } - else - { - sfunc = slot->pyobj; - Py_INCREF(sfunc); - } - - /* - * We make repeated attempts to call a slot. If we work out that it failed - * because of an immediate type error we try again with one less argument. - * We keep going until we run out of arguments to drop. This emulates the - * Qt ability of the slot to accept fewer arguments than a signal provides. - */ - sa = sigargs; - Py_INCREF(sa); - - for (;;) - { - PyObject *nsa, *xtype, *xvalue, *xtb, *resobj; - - if ((resobj = PyObject_CallObject(sfunc, sa)) != NULL) - { - Py_DECREF(sfunc); - Py_XDECREF(sref); - - /* Remove any previous exception. */ - - if (sa != sigargs) - { - Py_XDECREF(oxtype); - Py_XDECREF(oxvalue); - Py_XDECREF(oxtb); - PyErr_Clear(); - } - - Py_DECREF(sa); - - return resobj; - } - - /* Get the exception. */ - PyErr_Fetch(&xtype,&xvalue,&xtb); - - /* - * See if it is unacceptable. An acceptable failure is a type error - * with no traceback - so long as we can still reduce the number of - * arguments and try again. - */ - if (!PyErr_GivenExceptionMatches(xtype,PyExc_TypeError) || - xtb != NULL || - PyTuple_GET_SIZE(sa) == 0) - { - /* - * If there is a traceback then we must have called the slot and - * the exception was later on - so report the exception as is. - */ - if (xtb != NULL) - { - if (sa != sigargs) - { - Py_XDECREF(oxtype); - Py_XDECREF(oxvalue); - Py_XDECREF(oxtb); - } - - PyErr_Restore(xtype,xvalue,xtb); - } - else if (sa == sigargs) - PyErr_Restore(xtype,xvalue,xtb); - else - { - /* - * Discard the latest exception and restore the original one. - */ - Py_XDECREF(xtype); - Py_XDECREF(xvalue); - Py_XDECREF(xtb); - - PyErr_Restore(oxtype,oxvalue,oxtb); - } - - break; - } - - /* If this is the first attempt, save the exception. */ - if (sa == sigargs) - { - oxtype = xtype; - oxvalue = xvalue; - oxtb = xtb; - } - else - { - Py_XDECREF(xtype); - Py_XDECREF(xvalue); - Py_XDECREF(xtb); - } - - /* Create the new argument tuple. */ - if ((nsa = PyTuple_GetSlice(sa,0,PyTuple_GET_SIZE(sa) - 1)) == NULL) - { - /* Tidy up. */ - Py_XDECREF(oxtype); - Py_XDECREF(oxvalue); - Py_XDECREF(oxtb); - - break; - } - - Py_DECREF(sa); - sa = nsa; - } - - Py_DECREF(sfunc); - Py_XDECREF(sref); - - Py_DECREF(sa); - - return NULL; -} - - -/* - * Compare two slots to see if they are the same. - */ -int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot) -{ - assert(sipQtSupport); - assert(sipQtSupport->qt_same_name); - - /* See if they are signals or Qt slots, ie. they have a name. */ - if (slot != NULL) - { - if (sp->name == NULL || sp->name[0] == '\0') - return 0; - - return (sipQtSupport->qt_same_name(sp->name, slot) && sp->pyobj == rxObj); - } - - /* See if they are pure Python methods. */ - if (PyMethod_Check(rxObj)) - { - if (sp->pyobj != NULL) - return 0; - - return (sp->meth.mfunc == PyMethod_GET_FUNCTION(rxObj) - && sp->meth.mself == PyMethod_GET_SELF(rxObj)); - } - - /* See if they are wrapped C++ methods. */ - if (PyCFunction_Check(rxObj)) - { - if (sp->name == NULL || sp->name[0] != '\0') - return 0; - - return (sp->pyobj == PyCFunction_GET_SELF(rxObj) && - strcmp(&sp->name[1], ((PyCFunctionObject *)rxObj)->m_ml->ml_name) == 0); - } - - /* The objects must be the same. */ - return (sp->pyobj == rxObj); -} - - -/* - * Convert a valid Python signal or slot to an existing universal slot. - */ -void *sipGetRx(sipSimpleWrapper *txSelf, const char *sigargs, PyObject *rxObj, - const char *slot, const char **memberp) -{ - assert(sipQtSupport); - assert(sipQtSupport->qt_find_slot); - - if (slot != NULL) - if (isQtSlot(slot) || isQtSignal(slot)) - { - void *rx; - - *memberp = slot; - - if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL) - return NULL; - - if (isQtSignal(slot)) - rx = findSignal(rx, memberp); - - return rx; - } - - /* - * The slot was either a Python callable or PyQt3 Python signal so there - * should be a universal slot. - */ - return sipQtSupport->qt_find_slot(sip_api_get_address(txSelf), sigargs, rxObj, slot, memberp); -} - - -/* - * Convert a Python receiver (either a Python signal or slot or a Qt signal or - * slot) to a Qt receiver. It is only ever called when the signal is a Qt - * signal. Return NULL is there was an error. - */ -void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp, int flags) -{ - assert(sipQtSupport); - - if (slot == NULL) - return createUniversalSlot(txSelf, sigargs, rxObj, NULL, memberp, flags); - - if (isQtSlot(slot) || isQtSignal(slot)) - { - void *rx; - - *memberp = slot; - - if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL) - return NULL; - - if (isQtSignal(slot)) - rx = newSignal(rx, memberp); - - return rx; - } - - /* The slot is a Python signal so we need a universal slot to catch it. */ - return createUniversalSlot(txSelf, sigargs, rxObj, slot, memberp, 0); -} - - -/* - * Connect a Qt signal or a Python signal to a Qt slot, a Qt signal, a Python - * slot or a Python signal. This is all possible combinations. - */ -PyObject *sip_api_connect_rx(PyObject *txObj, const char *sig, PyObject *rxObj, - const char *slot, int type) -{ - assert(sipQtSupport); - assert(sipQtSupport->qt_connect); - - /* Handle Qt signals. */ - if (isQtSignal(sig)) - { - void *tx, *rx; - const char *member, *real_sig; - int res; - - if ((tx = sip_api_get_cpp_ptr((sipSimpleWrapper *)txObj, sipQObjectType)) == NULL) - return NULL; - - real_sig = sig; - - if ((tx = newSignal(tx, &real_sig)) == NULL) - return NULL; - - if ((rx = sip_api_convert_rx((sipWrapper *)txObj, sig, rxObj, slot, &member, 0)) == NULL) - return NULL; - - res = sipQtSupport->qt_connect(tx, real_sig, rx, member, type); - - return PyBool_FromLong(res); - } - - /* Handle Python signals. Only PyQt3 would get this far. */ - assert(sipQtSupport->qt_connect_py_signal); - - if (sipQtSupport->qt_connect_py_signal(txObj, sig, rxObj, slot) < 0) - return NULL; - - Py_INCREF(Py_True); - return Py_True; -} - - -/* - * Disconnect a signal to a signal or a Qt slot. - */ -PyObject *sip_api_disconnect_rx(PyObject *txObj,const char *sig, - PyObject *rxObj,const char *slot) -{ - assert(sipQtSupport); - assert(sipQtSupport->qt_disconnect); - assert(sipQtSupport->qt_destroy_universal_slot); - - /* Handle Qt signals. */ - if (isQtSignal(sig)) - { - sipSimpleWrapper *txSelf = (sipSimpleWrapper *)txObj; - void *tx, *rx; - const char *member; - int res; - - if ((tx = sip_api_get_cpp_ptr(txSelf, sipQObjectType)) == NULL) - return NULL; - - if ((rx = sipGetRx(txSelf, sig, rxObj, slot, &member)) == NULL) - { - Py_INCREF(Py_False); - return Py_False; - } - - /* Handle Python signals. */ - tx = findSignal(tx, &sig); - - res = sipQtSupport->qt_disconnect(tx, sig, rx, member); - - /* - * Delete it if it is a universal slot as this will be it's only - * connection. If the slot is actually a universal signal then it - * should leave it in place. - */ - sipQtSupport->qt_destroy_universal_slot(rx); - - return PyBool_FromLong(res); - } - - /* Handle Python signals. Only PyQt3 would get this far. */ - assert(sipQtSupport->qt_disconnect_py_signal); - - sipQtSupport->qt_disconnect_py_signal(txObj, sig, rxObj, slot); - - Py_INCREF(Py_True); - return Py_True; -} - - -/* - * Free the resources of a slot. - */ -void sip_api_free_sipslot(sipSlot *slot) -{ - assert(sipQtSupport); - - if (slot->name != NULL) - { - sip_api_free(slot->name); - } - else if (slot->weakSlot == Py_True) - { - Py_DECREF(slot->pyobj); - } - - /* Remove any weak reference. */ - Py_XDECREF(slot->weakSlot); -} - - -/* - * Implement strdup() using sip_api_malloc(). - */ -static char *sipStrdup(const char *s) -{ - char *d; - - if ((d = (char *)sip_api_malloc(strlen(s) + 1)) != NULL) - strcpy(d,s); - - return d; -} - - -/* - * Initialise a slot, returning 0 if there was no error. If the signal was a - * Qt signal, then the slot may be a Python signal or a Python slot. If the - * signal was a Python signal, then the slot may be anything. - */ -int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot) -{ - assert(sipQtSupport); - - sp -> weakSlot = NULL; - - if (slot == NULL) - { - sp -> name = NULL; - - if (PyMethod_Check(rxObj)) - { - /* - * Python creates methods on the fly. We could increment the - * reference count to keep it alive, but that would keep "self" - * alive as well and would probably be a circular reference. - * Instead we remember the component parts and hope they are still - * valid when we re-create the method when we need it. - */ - sipSaveMethod(&sp -> meth,rxObj); - - /* Notice if the class instance disappears. */ - sp -> weakSlot = getWeakRef(sp -> meth.mself); - - /* This acts a flag to say that the slot is a method. */ - sp -> pyobj = NULL; - } - else - { - PyObject *self; - - /* - * We know that it is another type of callable, ie. a - * function/builtin. - */ - - if (PyCFunction_Check(rxObj) && - (self = PyCFunction_GET_SELF(rxObj)) != NULL && - PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type)) - { - /* - * It is a wrapped C++ class method. We can't keep a copy - * because they are generated on the fly and we can't take a - * reference as that may keep the instance (ie. self) alive. - * We therefore treat it as if the user had specified the slot - * at "obj, SLOT('meth()')" rather than "obj.meth" (see below). - */ - - const char *meth; - - /* Get the method name. */ - meth = ((PyCFunctionObject *)rxObj) -> m_ml -> ml_name; - - if ((sp -> name = (char *)sip_api_malloc(strlen(meth) + 2)) == NULL) - return -1; - - /* - * Copy the name and set the marker that it needs converting to - * a built-in method. - */ - sp -> name[0] = '\0'; - strcpy(&sp -> name[1],meth); - - sp -> pyobj = self; - sp -> weakSlot = getWeakRef(self); - } - else - { - /* - * Give the slot an extra reference to keep it alive and - * remember we have done so by treating weakSlot specially. - */ - Py_INCREF(rxObj); - sp->pyobj = rxObj; - - Py_INCREF(Py_True); - sp->weakSlot = Py_True; - } - } - } - else if ((sp -> name = sipStrdup(slot)) == NULL) - return -1; - else if (isQtSlot(slot)) - { - /* - * The user has decided to connect a Python signal to a Qt slot and - * specified the slot as "obj, SLOT('meth()')" rather than "obj.meth". - */ - - char *tail; - - /* Remove any arguments. */ - if ((tail = strchr(sp -> name,'(')) != NULL) - *tail = '\0'; - - /* - * A bit of a hack to indicate that this needs converting to a built-in - * method. - */ - sp -> name[0] = '\0'; - - /* Notice if the class instance disappears. */ - sp -> weakSlot = getWeakRef(rxObj); - - sp -> pyobj = rxObj; - } - else - /* It's a Qt signal. */ - sp -> pyobj = rxObj; - - return 0; -} - - -/* - * Return a weak reference to the given object. - */ -static PyObject *getWeakRef(PyObject *obj) -{ - PyObject *wr; - - if ((wr = PyWeakref_NewRef(obj,NULL)) == NULL) - PyErr_Clear(); - - return wr; -} diff --git a/sip/siplib/sip.h b/sip/siplib/sip.h deleted file mode 100644 index 5f0f0591..00000000 --- a/sip/siplib/sip.h +++ /dev/null @@ -1,1909 +0,0 @@ -/* - * The SIP module interface. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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. - */ - - -#ifndef _SIP_H -#define _SIP_H - - -#include - -/* Sanity check on the Python version. */ -#if PY_VERSION_HEX < 0x03050000 -#error "This version of SIP requires Python v3.5 or later" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* The patch version of this implementation of the ABI. */ -#define SIP_MODULE_PATCH_VERSION 1 - - -/* - * The changes to this version of the ABI. - * - * Preserve any current exception in the wrapper tp_dealloc functions. - */ - - -/* The ABI version implemented. */ -#define SIP_ABI_MAJOR_VERSION 12 -#define SIP_ABI_MINOR_VERSION 8 - -/* The version of the code generator. */ -#define SIP_VERSION 0x50500 -#define SIP_VERSION_STR "5.5.0" - -/* These are all dependent on the user-specified name of the sip module. */ -#define _SIP_MODULE_FQ_NAME "wx.siplib" -#define _SIP_MODULE_NAME "siplib" -#define _SIP_MODULE_SHARED 1 -#define _SIP_MODULE_ENTRY PyInit_siplib -#define _SIP_MODULE_LEGACY 0 - -/* Support the historical names. */ -#define SIP_API_MAJOR_NR SIP_ABI_MAJOR_VERSION -#define SIP_API_MINOR_NR SIP_ABI_MINOR_VERSION - - -/* - * Qt includes this typedef and its meta-object system explicitly converts - * types to uint. If these correspond to signal arguments then that conversion - * is exposed. Therefore SIP generates code that uses it. This definition is - * for the cases that SIP is generating non-Qt related bindings with compilers - * that don't include it themselves (i.e. MSVC). - */ -typedef unsigned int uint; - - -/* Some C++ compatibility stuff. */ -#if defined(__cplusplus) - -/* - * Cast a PyCFunctionWithKeywords to a PyCFunction in such a way that it - * suppresses the GCC -Wcast-function-type warning. - */ -#define SIP_MLMETH_CAST(m) reinterpret_cast(reinterpret_cast(m)) - -#if __cplusplus >= 201103L || defined(_MSVC_LANG) - -/* C++11 and later. */ -#define SIP_NULLPTR nullptr -#define SIP_OVERRIDE override - -#else - -/* Earlier versions of C++. */ -#define SIP_NULLPTR NULL -#define SIP_OVERRIDE - -#endif - -#else - -/* Cast a PyCFunctionWithKeywords to a PyCFunction. */ -#define SIP_MLMETH_CAST(m) ((PyCFunction)(m)) - -/* C. */ -#define SIP_NULLPTR NULL -#define SIP_OVERRIDE - -#endif - - -/* Remove in v5.1. */ -#define SIP_SSIZE_T Py_ssize_t -#define SIP_SSIZE_T_FORMAT "%zd" -#define SIP_USE_PYCAPSULE -#define SIP_MODULE_RETURN(v) return (v) - -/* - * Remove in v5.1. These are undocumented and can be removed when PyQt5 drops - * support for Python v2. - */ -#define SIPLong_Check PyLong_Check -#define SIPLong_FromLong PyLong_FromLong -#define SIPLong_AsLong PyLong_AsLong - -#define SIPBytes_Check PyBytes_Check -#define SIPBytes_FromString PyBytes_FromString -#define SIPBytes_FromStringAndSize PyBytes_FromStringAndSize -#define SIPBytes_AsString PyBytes_AsString -#define SIPBytes_Size PyBytes_Size -#define SIPBytes_AS_STRING PyBytes_AS_STRING -#define SIPBytes_GET_SIZE PyBytes_GET_SIZE - - -/* - * The mask that can be passed to sipTrace(). - */ -#define SIP_TRACE_CATCHERS 0x0001 -#define SIP_TRACE_CTORS 0x0002 -#define SIP_TRACE_DTORS 0x0004 -#define SIP_TRACE_INITS 0x0008 -#define SIP_TRACE_DEALLOCS 0x0010 -#define SIP_TRACE_METHODS 0x0020 - - -/* - * Hide some thread dependent stuff. - */ -#ifdef WITH_THREAD -typedef PyGILState_STATE sip_gilstate_t; -#define SIP_RELEASE_GIL(gs) PyGILState_Release(gs); -#define SIP_BLOCK_THREADS {PyGILState_STATE sipGIL = PyGILState_Ensure(); -#define SIP_UNBLOCK_THREADS PyGILState_Release(sipGIL);} -#else -typedef int sip_gilstate_t; -#define SIP_RELEASE_GIL(gs) -#define SIP_BLOCK_THREADS -#define SIP_UNBLOCK_THREADS -#endif - - -/* - * Forward declarations of types. - */ -struct _sipBufferDef; -typedef struct _sipBufferDef sipBufferDef; - -struct _sipBufferInfoDef; -typedef struct _sipBufferInfoDef sipBufferInfoDef; - -struct _sipCFunctionDef; -typedef struct _sipCFunctionDef sipCFunctionDef; - -struct _sipDateDef; -typedef struct _sipDateDef sipDateDef; - -struct _sipEnumTypeObject; -typedef struct _sipEnumTypeObject sipEnumTypeObject; - -struct _sipMethodDef; -typedef struct _sipMethodDef sipMethodDef; - -struct _sipSimpleWrapper; -typedef struct _sipSimpleWrapper sipSimpleWrapper; - -struct _sipTimeDef; -typedef struct _sipTimeDef sipTimeDef; - -struct _sipTypeDef; -typedef struct _sipTypeDef sipTypeDef; - -struct _sipWrapperType; -typedef struct _sipWrapperType sipWrapperType; - -struct _sipWrapper; -typedef struct _sipWrapper sipWrapper; - - -/* - * The different events a handler can be registered for. - */ -typedef enum -{ - sipEventWrappedInstance, /* After wrapping a C/C++ instance. */ - sipEventCollectingWrapper, /* When garbage collecting a wrapper object. */ - sipEventNrEvents -} sipEventType; - -/* - * The event handlers. - */ -typedef void (*sipWrappedInstanceEventHandler)(void *sipCpp); -typedef void (*sipCollectingWrapperEventHandler)(sipSimpleWrapper *sipSelf); - - -/* - * The operation an access function is being asked to perform. - */ -typedef enum -{ - UnguardedPointer, /* Return the unguarded pointer. */ - GuardedPointer, /* Return the guarded pointer, ie. 0 if it has gone. */ - ReleaseGuard /* Release the guard, if any. */ -} AccessFuncOp; - - -/* - * Some convenient function pointers. - */ -typedef void *(*sipInitFunc)(sipSimpleWrapper *, PyObject *, PyObject *, - PyObject **, PyObject **, PyObject **); -typedef int (*sipFinalFunc)(PyObject *, void *, PyObject *, PyObject **); -typedef void *(*sipAccessFunc)(sipSimpleWrapper *, AccessFuncOp); -typedef int (*sipTraverseFunc)(void *, visitproc, void *); -typedef int (*sipClearFunc)(void *); -typedef int (*sipGetBufferFuncLimited)(PyObject *, void *, sipBufferDef *); -typedef void (*sipReleaseBufferFuncLimited)(PyObject *, void *); -#if !defined(Py_LIMITED_API) -typedef int (*sipGetBufferFunc)(PyObject *, void *, Py_buffer *, int); -typedef void (*sipReleaseBufferFunc)(PyObject *, void *, Py_buffer *); -#endif -typedef void (*sipDeallocFunc)(sipSimpleWrapper *); -typedef void *(*sipCastFunc)(void *, const sipTypeDef *); -typedef const sipTypeDef *(*sipSubClassConvertFunc)(void **); -typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *); -typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); -typedef void (*sipVirtErrorHandlerFunc)(sipSimpleWrapper *, sip_gilstate_t); -typedef int (*sipVirtHandlerFunc)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *, ...); -typedef void (*sipAssignFunc)(void *, Py_ssize_t, void *); -typedef void *(*sipArrayFunc)(Py_ssize_t); -typedef void *(*sipCopyFunc)(const void *, Py_ssize_t); -typedef void (*sipReleaseFunc)(void *, int); -typedef PyObject *(*sipPickleFunc)(void *); -typedef int (*sipAttrGetterFunc)(const sipTypeDef *, PyObject *); -typedef PyObject *(*sipVariableGetterFunc)(void *, PyObject *, PyObject *); -typedef int (*sipVariableSetterFunc)(void *, PyObject *, PyObject *); -typedef void *(*sipProxyResolverFunc)(void *); -typedef int (*sipNewUserTypeFunc)(sipWrapperType *); -typedef void (*sipWrapperVisitorFunc)(sipSimpleWrapper *, void *); - - -#if !defined(Py_LIMITED_API) -/* - * The meta-type of a wrapper type. - */ -struct _sipWrapperType { - /* - * The super-metatype. This must be first in the structure so that it can - * be cast to a PyTypeObject *. - */ - PyHeapTypeObject super; - - /* Set if the type is a user implemented Python sub-class. */ - unsigned wt_user_type : 1; - - /* Set if the type's dictionary contains all lazy attributes. */ - unsigned wt_dict_complete : 1; - - /* Unused and available for future use. */ - unsigned wt_unused : 30; - - /* The generated type structure. */ - sipTypeDef *wt_td; - - /* The list of init extenders. */ - struct _sipInitExtenderDef *wt_iextend; - - /* The handler called whenever a new user type has been created. */ - sipNewUserTypeFunc wt_new_user_type_handler; - - /* - * For the user to use. Note that any data structure will leak if the - * type is garbage collected. - */ - void *wt_user_data; -}; - - -/* - * The type of a simple C/C++ wrapper object. - */ -struct _sipSimpleWrapper { - PyObject_HEAD - - /* - * The data, initially a pointer to the C/C++ object, as interpreted by the - * access function. - */ - void *data; - - /* The optional access function. */ - sipAccessFunc access_func; - - /* Object flags. */ - unsigned sw_flags; - - /* The optional dictionary of extra references keyed by argument number. */ - PyObject *extra_refs; - - /* For the user to use. */ - PyObject *user; - - /* The instance dictionary. */ - PyObject *dict; - - /* The main instance if this is a mixin. */ - PyObject *mixin_main; - - /* Next object at this address. */ - struct _sipSimpleWrapper *next; -}; - - -/* - * The type of a C/C++ wrapper object that supports parent/child relationships. - */ -struct _sipWrapper { - /* The super-type. */ - sipSimpleWrapper super; - - /* First child object. */ - struct _sipWrapper *first_child; - - /* Next sibling. */ - struct _sipWrapper *sibling_next; - - /* Previous sibling. */ - struct _sipWrapper *sibling_prev; - - /* Owning object. */ - struct _sipWrapper *parent; -}; - - -/* - * Removed in v5.1. - * The meta-type of an enum type. (This is exposed only to support the - * deprecated sipConvertFromNamedEnum() macro.) - */ -struct _sipEnumTypeObject { - /* - * The super-metatype. This must be first in the structure so that it can - * be cast to a PyTypeObject *. - */ - PyHeapTypeObject super; - - /* The generated type structure. */ - struct _sipTypeDef *type; -}; -#endif - - -/* - * The information describing an encoded type ID. - */ -typedef struct _sipEncodedTypeDef { - /* The type number. */ - unsigned sc_type : 16; - - /* The module number (255 for this one). */ - unsigned sc_module : 8; - - /* A context specific flag. */ - unsigned sc_flag : 1; -} sipEncodedTypeDef; - - -/* - * The information describing an enum member. - */ -typedef struct _sipEnumMemberDef { - /* The member name. */ - const char *em_name; - - /* The member value. */ - int em_val; - - /* The member enum, -ve if anonymous. */ - int em_enum; -} sipEnumMemberDef; - - -/* - * The information describing static instances. - */ -typedef struct _sipInstancesDef { - /* The types. */ - struct _sipTypeInstanceDef *id_type; - - /* The void *. */ - struct _sipVoidPtrInstanceDef *id_voidp; - - /* The chars. */ - struct _sipCharInstanceDef *id_char; - - /* The strings. */ - struct _sipStringInstanceDef *id_string; - - /* The ints. */ - struct _sipIntInstanceDef *id_int; - - /* The longs. */ - struct _sipLongInstanceDef *id_long; - - /* The unsigned longs. */ - struct _sipUnsignedLongInstanceDef *id_ulong; - - /* The long longs. */ - struct _sipLongLongInstanceDef *id_llong; - - /* The unsigned long longs. */ - struct _sipUnsignedLongLongInstanceDef *id_ullong; - - /* The doubles. */ - struct _sipDoubleInstanceDef *id_double; -} sipInstancesDef; - - -/* - * The information describing a type initialiser extender. - */ -typedef struct _sipInitExtenderDef { - /* The API version range index. */ - int ie_api_range; - - /* The extender function. */ - sipInitFunc ie_extender; - - /* The class being extended. */ - sipEncodedTypeDef ie_class; - - /* The next extender for this class. */ - struct _sipInitExtenderDef *ie_next; -} sipInitExtenderDef; - - -/* - * The information describing a sub-class converter. - */ -typedef struct _sipSubClassConvertorDef { - /* The converter. */ - sipSubClassConvertFunc scc_convertor; - - /* The encoded base type. */ - sipEncodedTypeDef scc_base; - - /* The base type. */ - struct _sipTypeDef *scc_basetype; -} sipSubClassConvertorDef; - - -/* - * The structure populated by %BIGetBufferCode when the limited API is enabled. - */ -struct _sipBufferDef { - /* The address of the buffer. */ - void *bd_buffer; - - /* The length of the buffer. */ - Py_ssize_t bd_length; - - /* Set if the buffer is read-only. */ - int bd_readonly; -}; - - -/* - * The structure describing a Python buffer. - */ -struct _sipBufferInfoDef { - /* This is internal to sip. */ - void *bi_internal; - - /* The address of the buffer. */ - void *bi_buf; - - /* A reference to the object implementing the buffer interface. */ - PyObject *bi_obj; - - /* The length of the buffer in bytes. */ - Py_ssize_t bi_len; - - /* The number of dimensions. */ - int bi_ndim; - - /* The format of each element of the buffer. */ - char *bi_format; -}; - - -/* - * The structure describing a Python C function. - */ -struct _sipCFunctionDef { - /* The C function. */ - PyMethodDef *cf_function; - - /* The optional bound object. */ - PyObject *cf_self; -}; - - -/* - * The structure describing a Python method. - */ -struct _sipMethodDef { - /* The function that implements the method. */ - PyObject *pm_function; - - /* The bound object. */ - PyObject *pm_self; -}; - - -/* - * The structure describing a Python date. - */ -struct _sipDateDef { - /* The year. */ - int pd_year; - - /* The month (1-12). */ - int pd_month; - - /* The day (1-31). */ - int pd_day; -}; - - -/* - * The structure describing a Python time. - */ -struct _sipTimeDef { - /* The hour (0-23). */ - int pt_hour; - - /* The minute (0-59). */ - int pt_minute; - - /* The second (0-59). */ - int pt_second; - - /* The microsecond (0-999999). */ - int pt_microsecond; -}; - - -/* - * The different error states of handwritten code. - */ -typedef enum { - sipErrorNone, /* There is no error. */ - sipErrorFail, /* The error is a failure. */ - sipErrorContinue /* It may not apply if a later operation succeeds. */ -} sipErrorState; - - -/* - * The different Python slot types. New slots must be added to the end, - * otherwise the major version of the internal ABI must be changed. - */ -typedef enum { - str_slot, /* __str__ */ - int_slot, /* __int__ */ - float_slot, /* __float__ */ - len_slot, /* __len__ */ - contains_slot, /* __contains__ */ - add_slot, /* __add__ for number */ - concat_slot, /* __add__ for sequence types */ - sub_slot, /* __sub__ */ - mul_slot, /* __mul__ for number types */ - repeat_slot, /* __mul__ for sequence types */ - div_slot, /* __div__ */ - mod_slot, /* __mod__ */ - floordiv_slot, /* __floordiv__ */ - truediv_slot, /* __truediv__ */ - and_slot, /* __and__ */ - or_slot, /* __or__ */ - xor_slot, /* __xor__ */ - lshift_slot, /* __lshift__ */ - rshift_slot, /* __rshift__ */ - iadd_slot, /* __iadd__ for number types */ - iconcat_slot, /* __iadd__ for sequence types */ - isub_slot, /* __isub__ */ - imul_slot, /* __imul__ for number types */ - irepeat_slot, /* __imul__ for sequence types */ - idiv_slot, /* __idiv__ */ - imod_slot, /* __imod__ */ - ifloordiv_slot, /* __ifloordiv__ */ - itruediv_slot, /* __itruediv__ */ - iand_slot, /* __iand__ */ - ior_slot, /* __ior__ */ - ixor_slot, /* __ixor__ */ - ilshift_slot, /* __ilshift__ */ - irshift_slot, /* __irshift__ */ - invert_slot, /* __invert__ */ - call_slot, /* __call__ */ - getitem_slot, /* __getitem__ */ - setitem_slot, /* __setitem__ */ - delitem_slot, /* __delitem__ */ - lt_slot, /* __lt__ */ - le_slot, /* __le__ */ - eq_slot, /* __eq__ */ - ne_slot, /* __ne__ */ - gt_slot, /* __gt__ */ - ge_slot, /* __ge__ */ - bool_slot, /* __bool__, __nonzero__ */ - neg_slot, /* __neg__ */ - repr_slot, /* __repr__ */ - hash_slot, /* __hash__ */ - pos_slot, /* __pos__ */ - abs_slot, /* __abs__ */ - index_slot, /* __index__ */ - iter_slot, /* __iter__ */ - next_slot, /* __next__ */ - setattr_slot, /* __setattr__, __delattr__ */ - matmul_slot, /* __matmul__ (for Python v3.5 and later) */ - imatmul_slot, /* __imatmul__ (for Python v3.5 and later) */ - await_slot, /* __await__ (for Python v3.5 and later) */ - aiter_slot, /* __aiter__ (for Python v3.5 and later) */ - anext_slot, /* __anext__ (for Python v3.5 and later) */ -} sipPySlotType; - - -/* - * The information describing a Python slot function. - */ -typedef struct _sipPySlotDef { - /* The function. */ - void *psd_func; - - /* The type. */ - sipPySlotType psd_type; -} sipPySlotDef; - - -/* - * The information describing a Python slot extender. - */ -typedef struct _sipPySlotExtenderDef { - /* The function. */ - void *pse_func; - - /* The type. */ - sipPySlotType pse_type; - - /* The encoded class. */ - sipEncodedTypeDef pse_class; -} sipPySlotExtenderDef; - - -/* - * The information describing a typedef. - */ -typedef struct _sipTypedefDef { - /* The typedef name. */ - const char *tdd_name; - - /* The typedef value. */ - const char *tdd_type_name; -} sipTypedefDef; - - -/* - * The information describing a variable or property. - */ - -typedef enum -{ - PropertyVariable, /* A property. */ - InstanceVariable, /* An instance variable. */ - ClassVariable /* A class (i.e. static) variable. */ -} sipVariableType; - -typedef struct _sipVariableDef { - /* The type of variable. */ - sipVariableType vd_type; - - /* The name. */ - const char *vd_name; - - /* - * The getter. If this is a variable (rather than a property) then the - * actual type is sipVariableGetterFunc. - */ - PyMethodDef *vd_getter; - - /* - * The setter. If this is a variable (rather than a property) then the - * actual type is sipVariableSetterFunc. It is NULL if the property cannot - * be set or the variable is const. - */ - PyMethodDef *vd_setter; - - /* The property deleter. */ - PyMethodDef *vd_deleter; - - /* The docstring. */ - const char *vd_docstring; -} sipVariableDef; - - -/* - * The information describing a type, either a C++ class (or C struct), a C++ - * namespace, a mapped type or a named enum. - */ -struct _sipTypeDef { - /* The version range index, -1 if the type isn't versioned. */ - int td_version; - - /* The next version of this type. */ - struct _sipTypeDef *td_next_version; - - /* - * The module, 0 if the type hasn't been initialised. - */ - struct _sipExportedModuleDef *td_module; - - /* Type flags, see the sipType*() macros. */ - int td_flags; - - /* The C/C++ name of the type. */ - int td_cname; - - /* The Python type object. */ - PyTypeObject *td_py_type; - - /* Any additional fixed data generated by a plugin. */ - void *td_plugin_data; -}; - - -/* - * The information describing a container (ie. a class, namespace or a mapped - * type). - */ -typedef struct _sipContainerDef { - /* - * The Python name of the type, -1 if this is a namespace extender (in the - * context of a class) or doesn't require a namespace (in the context of a - * mapped type). */ - int cod_name; - - /* - * The scoping type or the namespace this is extending if it is a namespace - * extender. - */ - sipEncodedTypeDef cod_scope; - - /* The number of lazy methods. */ - int cod_nrmethods; - - /* The table of lazy methods. */ - PyMethodDef *cod_methods; - - /* The number of lazy enum members. */ - int cod_nrenummembers; - - /* The table of lazy enum members. */ - sipEnumMemberDef *cod_enummembers; - - /* The number of variables. */ - int cod_nrvariables; - - /* The table of variables. */ - sipVariableDef *cod_variables; - - /* The static instances. */ - sipInstancesDef cod_instances; -} sipContainerDef; - - -/* - * The information describing a C++ class (or C struct) or a C++ namespace. - */ -typedef struct _sipClassTypeDef { - /* The base type information. */ - sipTypeDef ctd_base; - - /* The container information. */ - sipContainerDef ctd_container; - - /* The docstring. */ - const char *ctd_docstring; - - /* - * The meta-type name, -1 to use the meta-type of the first super-type - * (normally sipWrapperType). - */ - int ctd_metatype; - - /* The super-type name, -1 to use sipWrapper. */ - int ctd_supertype; - - /* The super-types. */ - sipEncodedTypeDef *ctd_supers; - - /* The table of Python slots. */ - sipPySlotDef *ctd_pyslots; - - /* The initialisation function. */ - sipInitFunc ctd_init; - - /* The traverse function. */ - sipTraverseFunc ctd_traverse; - - /* The clear function. */ - sipClearFunc ctd_clear; - - /* The get buffer function. */ -#if defined(Py_LIMITED_API) - sipGetBufferFuncLimited ctd_getbuffer; -#else - sipGetBufferFunc ctd_getbuffer; -#endif - - /* The release buffer function. */ -#if defined(Py_LIMITED_API) - sipReleaseBufferFuncLimited ctd_releasebuffer; -#else - sipReleaseBufferFunc ctd_releasebuffer; -#endif - - /* The deallocation function. */ - sipDeallocFunc ctd_dealloc; - - /* The optional assignment function. */ - sipAssignFunc ctd_assign; - - /* The optional array allocation function. */ - sipArrayFunc ctd_array; - - /* The optional copy function. */ - sipCopyFunc ctd_copy; - - /* The release function, 0 if a C struct. */ - sipReleaseFunc ctd_release; - - /* The cast function, 0 if a C struct. */ - sipCastFunc ctd_cast; - - /* The optional convert to function. */ - sipConvertToFunc ctd_cto; - - /* The optional convert from function. */ - sipConvertFromFunc ctd_cfrom; - - /* The next namespace extender. */ - struct _sipClassTypeDef *ctd_nsextender; - - /* The pickle function. */ - sipPickleFunc ctd_pickle; - - /* The finalisation function. */ - sipFinalFunc ctd_final; - - /* The mixin initialisation function. */ - initproc ctd_init_mixin; -} sipClassTypeDef; - - -/* - * The information describing a mapped type. - */ -typedef struct _sipMappedTypeDef { - /* The base type information. */ - sipTypeDef mtd_base; - - /* The container information. */ - sipContainerDef mtd_container; - - /* The optional assignment function. */ - sipAssignFunc mtd_assign; - - /* The optional array allocation function. */ - sipArrayFunc mtd_array; - - /* The optional copy function. */ - sipCopyFunc mtd_copy; - - /* The optional release function. */ - sipReleaseFunc mtd_release; - - /* The convert to function. */ - sipConvertToFunc mtd_cto; - - /* The convert from function. */ - sipConvertFromFunc mtd_cfrom; -} sipMappedTypeDef; - - -/* - * The information describing a named enum. - */ -typedef struct _sipEnumTypeDef { - /* The base type information. */ - sipTypeDef etd_base; - - /* The Python name of the enum. */ - int etd_name; - - /* The scoping type, -1 if it is defined at the module level. */ - int etd_scope; - - /* The Python slots. */ - struct _sipPySlotDef *etd_pyslots; -} sipEnumTypeDef; - - -/* - * The information describing an external type. - */ -typedef struct _sipExternalTypeDef { - /* The index into the type table. */ - int et_nr; - - /* The name of the type. */ - const char *et_name; -} sipExternalTypeDef; - - -/* - * Remove in v5.1. - * The information describing a mapped class. This (and anything that uses it) - * is deprecated. - */ -typedef sipTypeDef sipMappedType; - - -/* - * Defines an entry in the module specific list of delayed dtor calls. - */ -typedef struct _sipDelayedDtor { - /* The C/C++ instance. */ - void *dd_ptr; - - /* The class name. */ - const char *dd_name; - - /* Non-zero if dd_ptr is a derived class instance. */ - int dd_isderived; - - /* Next in the list. */ - struct _sipDelayedDtor *dd_next; -} sipDelayedDtor; - - -/* - * Defines an entry in the table of global functions all of whose overloads - * are versioned (so their names can't be automatically added to the module - * dictionary). - */ -typedef struct _sipVersionedFunctionDef { - /* The name, -1 marks the end of the table. */ - int vf_name; - - /* The function itself. */ - PyCFunction vf_function; - - /* The METH_* flags. */ - int vf_flags; - - /* The docstring. */ - const char *vf_docstring; - - /* The API version range index. */ - int vf_api_range; -} sipVersionedFunctionDef; - - -/* - * Defines a virtual error handler. - */ -typedef struct _sipVirtErrorHandlerDef { - /* The name of the handler. */ - const char *veh_name; - - /* The handler function. */ - sipVirtErrorHandlerFunc veh_handler; -} sipVirtErrorHandlerDef; - - -/* - * Defines a type imported from another module. - */ -typedef union _sipImportedTypeDef { - /* The type name before the module is imported. */ - const char *it_name; - - /* The type after the module is imported. */ - sipTypeDef *it_td; -} sipImportedTypeDef; - - -/* - * Defines a virtual error handler imported from another module. - */ -typedef union _sipImportedVirtErrorHandlerDef { - /* The handler name before the module is imported. */ - const char *iveh_name; - - /* The handler after the module is imported. */ - sipVirtErrorHandlerFunc iveh_handler; -} sipImportedVirtErrorHandlerDef; - - -/* - * Defines an exception imported from another module. - */ -typedef union _sipImportedExceptionDef { - /* The exception name before the module is imported. */ - const char *iexc_name; - - /* The exception object after the module is imported. */ - PyObject *iexc_object; -} sipImportedExceptionDef; - - -/* - * The information describing an imported module. - */ -typedef struct _sipImportedModuleDef { - /* The module name. */ - const char *im_name; - - /* The types imported from the module. */ - sipImportedTypeDef *im_imported_types; - - /* The virtual error handlers imported from the module. */ - sipImportedVirtErrorHandlerDef *im_imported_veh; - - /* The exceptions imported from the module. */ - sipImportedExceptionDef *im_imported_exceptions; -} sipImportedModuleDef; - - -/* - * The main client module structure. - */ -typedef struct _sipExportedModuleDef { - /* The next in the list. */ - struct _sipExportedModuleDef *em_next; - - /* The SIP API minor version number. */ - unsigned em_api_minor; - - /* The module name. */ - int em_name; - - /* The module name as an object. */ - PyObject *em_nameobj; - - /* The string pool. */ - const char *em_strings; - - /* The imported modules. */ - sipImportedModuleDef *em_imports; - - /* The optional Qt support API. */ - struct _sipQtAPI *em_qt_api; - - /* The number of types. */ - int em_nrtypes; - - /* The table of types. */ - sipTypeDef **em_types; - - /* The table of external types. */ - sipExternalTypeDef *em_external; - - /* The number of members in global enums. */ - int em_nrenummembers; - - /* The table of members in global enums. */ - sipEnumMemberDef *em_enummembers; - - /* The number of typedefs. */ - int em_nrtypedefs; - - /* The table of typedefs. */ - sipTypedefDef *em_typedefs; - - /* The table of virtual error handlers. */ - sipVirtErrorHandlerDef *em_virterrorhandlers; - - /* The sub-class converters. */ - sipSubClassConvertorDef *em_convertors; - - /* The static instances. */ - sipInstancesDef em_instances; - - /* The license. */ - struct _sipLicenseDef *em_license; - - /* The table of exception types. */ - PyObject **em_exceptions; - - /* The table of Python slot extenders. */ - sipPySlotExtenderDef *em_slotextend; - - /* The table of initialiser extenders. */ - sipInitExtenderDef *em_initextend; - - /* The delayed dtor handler. */ - void (*em_delayeddtors)(const sipDelayedDtor *); - - /* The list of delayed dtors. */ - sipDelayedDtor *em_ddlist; - - /* - * The array of API version definitions. Each definition takes up 3 - * elements. If the third element of a 3-tuple is negative then the first - * two elements define an API and its default version. All such - * definitions will appear at the end of the array. If the first element - * of a 3-tuple is negative then that is the last element of the array. - */ - int *em_versions; - - /* The optional table of versioned functions. */ - sipVersionedFunctionDef *em_versioned_functions; -} sipExportedModuleDef; - - -/* - * The information describing a license to be added to a dictionary. - */ -typedef struct _sipLicenseDef { - /* The type of license. */ - const char *lc_type; - - /* The licensee. */ - const char *lc_licensee; - - /* The timestamp. */ - const char *lc_timestamp; - - /* The signature. */ - const char *lc_signature; -} sipLicenseDef; - - -/* - * The information describing a void pointer instance to be added to a - * dictionary. - */ -typedef struct _sipVoidPtrInstanceDef { - /* The void pointer name. */ - const char *vi_name; - - /* The void pointer value. */ - void *vi_val; -} sipVoidPtrInstanceDef; - - -/* - * The information describing a char instance to be added to a dictionary. - */ -typedef struct _sipCharInstanceDef { - /* The char name. */ - const char *ci_name; - - /* The char value. */ - char ci_val; - - /* The encoding used, either 'A', 'L', '8' or 'N'. */ - char ci_encoding; -} sipCharInstanceDef; - - -/* - * The information describing a string instance to be added to a dictionary. - * This is also used as a hack to add (or fix) other types rather than add a - * new table type and so requiring a new major version of the API. - */ -typedef struct _sipStringInstanceDef { - /* The string name. */ - const char *si_name; - - /* The string value. */ - const char *si_val; - - /* - * The encoding used, either 'A', 'L', '8' or 'N'. 'w' and 'W' are also - * used to support the fix for wchar_t. - */ - char si_encoding; -} sipStringInstanceDef; - - -/* - * The information describing an int instance to be added to a dictionary. - */ -typedef struct _sipIntInstanceDef { - /* The int name. */ - const char *ii_name; - - /* The int value. */ - int ii_val; -} sipIntInstanceDef; - - -/* - * The information describing a long instance to be added to a dictionary. - */ -typedef struct _sipLongInstanceDef { - /* The long name. */ - const char *li_name; - - /* The long value. */ - long li_val; -} sipLongInstanceDef; - - -/* - * The information describing an unsigned long instance to be added to a - * dictionary. - */ -typedef struct _sipUnsignedLongInstanceDef { - /* The unsigned long name. */ - const char *uli_name; - - /* The unsigned long value. */ - unsigned long uli_val; -} sipUnsignedLongInstanceDef; - - -/* - * The information describing a long long instance to be added to a dictionary. - */ -typedef struct _sipLongLongInstanceDef { - /* The long long name. */ - const char *lli_name; - - /* The long long value. */ -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG lli_val; -#else - long lli_val; -#endif -} sipLongLongInstanceDef; - - -/* - * The information describing an unsigned long long instance to be added to a - * dictionary. - */ -typedef struct _sipUnsignedLongLongInstanceDef { - /* The unsigned long long name. */ - const char *ulli_name; - - /* The unsigned long long value. */ -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG ulli_val; -#else - unsigned long ulli_val; -#endif -} sipUnsignedLongLongInstanceDef; - - -/* - * The information describing a double instance to be added to a dictionary. - */ -typedef struct _sipDoubleInstanceDef { - /* The double name. */ - const char *di_name; - - /* The double value. */ - double di_val; -} sipDoubleInstanceDef; - - -/* - * The information describing a class or enum instance to be added to a - * dictionary. - */ -typedef struct _sipTypeInstanceDef { - /* The type instance name. */ - const char *ti_name; - - /* The actual instance. */ - void *ti_ptr; - - /* A pointer to the generated type. */ - struct _sipTypeDef **ti_type; - - /* The wrapping flags. */ - int ti_flags; -} sipTypeInstanceDef; - - -/* - * Remove in v5.1. - * Define a mapping between a wrapped type identified by a string and the - * corresponding Python type. - */ -typedef struct _sipStringTypeClassMap { - /* The type as a string. */ - const char *typeString; - - /* A pointer to the Python type. */ - struct _sipWrapperType **pyType; -} sipStringTypeClassMap; - - -/* - * Remove in v5.1. - * Define a mapping between a wrapped type identified by an integer and the - * corresponding Python type. - */ -typedef struct _sipIntTypeClassMap { - /* The type as an integer. */ - int typeInt; - - /* A pointer to the Python type. */ - struct _sipWrapperType **pyType; -} sipIntTypeClassMap; - - -/* - * A Python method's component parts. This allows us to re-create the method - * without changing the reference counts of the components. - */ -typedef struct _sipPyMethod { - /* The function. */ - PyObject *mfunc; - - /* Self if it is a bound method. */ - PyObject *mself; -} sipPyMethod; - - -/* - * A slot (in the Qt, rather than Python, sense). - */ -typedef struct _sipSlot { - /* Name if a Qt or Python signal. */ - char *name; - - /* Signal or Qt slot object. */ - PyObject *pyobj; - - /* Python slot method, pyobj is NULL. */ - sipPyMethod meth; - - /* A weak reference to the slot, Py_True if pyobj has an extra reference. */ - PyObject *weakSlot; -} sipSlot; - - -/* - * The API exported by the SIP module, ie. pointers to all the data and - * functions that can be used by generated code. - */ -typedef struct _sipAPIDef { - /* - * This must be the first entry and it's signature must not change so that - * version number mismatches can be detected and reported. - */ - int (*api_export_module)(sipExportedModuleDef *client, unsigned api_major, - unsigned api_minor, void *unused); - - /* - * The following are part of the public API. - */ - PyTypeObject *api_simplewrapper_type; - PyTypeObject *api_wrapper_type; - PyTypeObject *api_wrappertype_type; - PyTypeObject *api_voidptr_type; - - void (*api_bad_catcher_result)(PyObject *method); - void (*api_bad_length_for_slice)(Py_ssize_t seqlen, Py_ssize_t slicelen); - PyObject *(*api_build_result)(int *isErr, const char *fmt, ...); - PyObject *(*api_call_method)(int *isErr, PyObject *method, const char *fmt, - ...); - void (*api_call_procedure_method)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *, const char *, ...); - PyObject *(*api_connect_rx)(PyObject *txObj, const char *sig, - PyObject *rxObj, const char *slot, int type); - Py_ssize_t (*api_convert_from_sequence_index)(Py_ssize_t idx, - Py_ssize_t len); - int (*api_can_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - int flags); - void *(*api_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp); - void *(*api_force_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp); - - /* - * The following are deprecated parts of the public API. - */ - int (*api_can_convert_to_enum)(PyObject *pyObj, const sipTypeDef *td); - - /* - * The following are part of the public API. - */ - void (*api_release_type)(void *cpp, const sipTypeDef *td, int state); - PyObject *(*api_convert_from_type)(void *cpp, const sipTypeDef *td, - PyObject *transferObj); - PyObject *(*api_convert_from_new_type)(void *cpp, const sipTypeDef *td, - PyObject *transferObj); - PyObject *(*api_convert_from_enum)(int eval, const sipTypeDef *td); - int (*api_get_state)(PyObject *transferObj); - PyObject *(*api_disconnect_rx)(PyObject *txObj, const char *sig, - PyObject *rxObj, const char *slot); - void (*api_free)(void *mem); - PyObject *(*api_get_pyobject)(void *cppPtr, const sipTypeDef *td); - void *(*api_malloc)(size_t nbytes); - int (*api_parse_result)(int *isErr, PyObject *method, PyObject *res, - const char *fmt, ...); - void (*api_trace)(unsigned mask, const char *fmt, ...); - void (*api_transfer_back)(PyObject *self); - void (*api_transfer_to)(PyObject *self, PyObject *owner); - void (*api_transfer_break)(PyObject *self); - unsigned long (*api_long_as_unsigned_long)(PyObject *o); - PyObject *(*api_convert_from_void_ptr)(void *val); - PyObject *(*api_convert_from_const_void_ptr)(const void *val); - PyObject *(*api_convert_from_void_ptr_and_size)(void *val, - Py_ssize_t size); - PyObject *(*api_convert_from_const_void_ptr_and_size)(const void *val, - Py_ssize_t size); - void *(*api_convert_to_void_ptr)(PyObject *obj); - int (*api_export_symbol)(const char *name, void *sym); - void *(*api_import_symbol)(const char *name); - const sipTypeDef *(*api_find_type)(const char *type); - int (*api_register_py_type)(PyTypeObject *type); - const sipTypeDef *(*api_type_from_py_type_object)(PyTypeObject *py_type); - const sipTypeDef *(*api_type_scope)(const sipTypeDef *td); - const char *(*api_resolve_typedef)(const char *name); - int (*api_register_attribute_getter)(const sipTypeDef *td, - sipAttrGetterFunc getter); - int (*api_is_api_enabled)(const char *name, int from, int to); - sipErrorState (*api_bad_callable_arg)(int arg_nr, PyObject *arg); - void *(*api_get_address)(struct _sipSimpleWrapper *w); - void (*api_set_destroy_on_exit)(int); - int (*api_enable_autoconversion)(const sipTypeDef *td, int enable); - void *(*api_get_mixin_address)(struct _sipSimpleWrapper *w, - const sipTypeDef *td); - PyObject *(*api_convert_from_new_pytype)(void *cpp, PyTypeObject *py_type, - sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...); - PyObject *(*api_convert_to_typed_array)(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags); - PyObject *(*api_convert_to_array)(void *data, const char *format, - Py_ssize_t len, int flags); - int (*api_register_proxy_resolver)(const sipTypeDef *td, - sipProxyResolverFunc resolver); - PyInterpreterState *(*api_get_interpreter)(void); - sipNewUserTypeFunc (*api_set_new_user_type_handler)(const sipTypeDef *, - sipNewUserTypeFunc); - void (*api_set_type_user_data)(sipWrapperType *, void *); - void *(*api_get_type_user_data)(const sipWrapperType *); - PyObject *(*api_py_type_dict)(const PyTypeObject *); - const char *(*api_py_type_name)(const PyTypeObject *); - int (*api_get_method)(PyObject *, sipMethodDef *); - PyObject *(*api_from_method)(const sipMethodDef *); - int (*api_get_c_function)(PyObject *, sipCFunctionDef *); - int (*api_get_date)(PyObject *, sipDateDef *); - PyObject *(*api_from_date)(const sipDateDef *); - int (*api_get_datetime)(PyObject *, sipDateDef *, sipTimeDef *); - PyObject *(*api_from_datetime)(const sipDateDef *, const sipTimeDef *); - int (*api_get_time)(PyObject *, sipTimeDef *); - PyObject *(*api_from_time)(const sipTimeDef *); - int (*api_is_user_type)(const sipWrapperType *); - struct _frame *(*api_get_frame)(int); - int (*api_check_plugin_for_type)(const sipTypeDef *, const char *); - PyObject *(*api_unicode_new)(Py_ssize_t, unsigned, int *, void **); - void (*api_unicode_write)(int, void *, int, unsigned); - void *(*api_unicode_data)(PyObject *, int *, Py_ssize_t *); - int (*api_get_buffer_info)(PyObject *, sipBufferInfoDef *); - void (*api_release_buffer_info)(sipBufferInfoDef *); - PyObject *(*api_get_user_object)(const sipSimpleWrapper *); - void (*api_set_user_object)(sipSimpleWrapper *, PyObject *); - - /* - * The following are not part of the public API. - */ - int (*api_init_module)(sipExportedModuleDef *client, PyObject *mod_dict); - int (*api_parse_args)(PyObject **parseErrp, PyObject *sipArgs, - const char *fmt, ...); - int (*api_parse_pair)(PyObject **parseErrp, PyObject *arg0, PyObject *arg1, - const char *fmt, ...); - - /* - * The following are part of the public API. - */ - void (*api_instance_destroyed)(sipSimpleWrapper *sipSelf); - - /* - * The following are not part of the public API. - */ - void (*api_no_function)(PyObject *parseErr, const char *func, - const char *doc); - void (*api_no_method)(PyObject *parseErr, const char *scope, - const char *method, const char *doc); - void (*api_abstract_method)(const char *classname, const char *method); - void (*api_bad_class)(const char *classname); - void *(*api_get_cpp_ptr)(sipSimpleWrapper *w, const sipTypeDef *td); - void *(*api_get_complex_cpp_ptr)(sipSimpleWrapper *w); - PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper *sipSelf, const char *cname, const char *mname); - void (*api_call_hook)(const char *hookname); - void (*api_end_thread)(void); - void (*api_raise_unknown_exception)(void); - void (*api_raise_type_exception)(const sipTypeDef *td, void *ptr); - int (*api_add_type_instance)(PyObject *dict, const char *name, - void *cppPtr, const sipTypeDef *td); - void (*api_bad_operator_arg)(PyObject *self, PyObject *arg, - sipPySlotType st); - PyObject *(*api_pyslot_extend)(sipExportedModuleDef *mod, sipPySlotType st, - const sipTypeDef *type, PyObject *arg0, PyObject *arg1); - void (*api_add_delayed_dtor)(sipSimpleWrapper *w); - char (*api_bytes_as_char)(PyObject *obj); - const char *(*api_bytes_as_string)(PyObject *obj); - char (*api_string_as_ascii_char)(PyObject *obj); - const char *(*api_string_as_ascii_string)(PyObject **obj); - char (*api_string_as_latin1_char)(PyObject *obj); - const char *(*api_string_as_latin1_string)(PyObject **obj); - char (*api_string_as_utf8_char)(PyObject *obj); - const char *(*api_string_as_utf8_string)(PyObject **obj); -#if defined(HAVE_WCHAR_H) - wchar_t (*api_unicode_as_wchar)(PyObject *obj); - wchar_t *(*api_unicode_as_wstring)(PyObject *obj); -#else - int (*api_unicode_as_wchar)(PyObject *obj); - int *(*api_unicode_as_wstring)(PyObject *obj); -#endif - int (*api_deprecated)(const char *classname, const char *method); - void (*api_keep_reference)(PyObject *self, int key, PyObject *obj); - int (*api_parse_kwd_args)(PyObject **parseErrp, PyObject *sipArgs, - PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, - const char *fmt, ...); - void (*api_add_exception)(sipErrorState es, PyObject **parseErrp); - int (*api_parse_result_ex)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *method, PyObject *res, - const char *fmt, ...); - void (*api_call_error_handler)(sipVirtErrorHandlerFunc, - sipSimpleWrapper *, sip_gilstate_t); - int (*api_init_mixin)(PyObject *self, PyObject *args, PyObject *kwds, - const sipClassTypeDef *ctd); - PyObject *(*api_get_reference)(PyObject *self, int key); - - /* - * The following are part of the public API. - */ - int (*api_is_owned_by_python)(sipSimpleWrapper *); - - /* - * The following are not part of the public API. - */ - int (*api_is_derived_class)(sipSimpleWrapper *); - - /* - * The following may be used by Qt support code but no other handwritten - * code. - */ - void (*api_free_sipslot)(sipSlot *slot); - int (*api_same_slot)(const sipSlot *sp, PyObject *rxObj, const char *slot); - void *(*api_convert_rx)(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp, - int flags); - PyObject *(*api_invoke_slot)(const sipSlot *slot, PyObject *sigargs); - PyObject *(*api_invoke_slot_ex)(const sipSlot *slot, PyObject *sigargs, - int check_receiver); - int (*api_save_slot)(sipSlot *sp, PyObject *rxObj, const char *slot); - void (*api_clear_any_slot_reference)(sipSlot *slot); - int (*api_visit_slot)(sipSlot *slot, visitproc visit, void *arg); - - /* - * The following are deprecated parts of the public API. - */ - PyTypeObject *(*api_find_named_enum)(const char *type); - const sipMappedType *(*api_find_mapped_type)(const char *type); - sipWrapperType *(*api_find_class)(const char *type); - sipWrapperType *(*api_map_int_to_class)(int typeInt, - const sipIntTypeClassMap *map, int maplen); - sipWrapperType *(*api_map_string_to_class)(const char *typeString, - const sipStringTypeClassMap *map, int maplen); - - /* - * The following are part of the public API. - */ - int (*api_enable_gc)(int enable); - void (*api_print_object)(PyObject *o); - int (*api_register_event_handler)(sipEventType type, const sipTypeDef *td, - void *handler); - int (*api_convert_to_enum)(PyObject *obj, const sipTypeDef *td); - int (*api_convert_to_bool)(PyObject *obj); - int (*api_enable_overflow_checking)(int enable); - char (*api_long_as_char)(PyObject *o); - signed char (*api_long_as_signed_char)(PyObject *o); - unsigned char (*api_long_as_unsigned_char)(PyObject *o); - short (*api_long_as_short)(PyObject *o); - unsigned short (*api_long_as_unsigned_short)(PyObject *o); - int (*api_long_as_int)(PyObject *o); - unsigned int (*api_long_as_unsigned_int)(PyObject *o); - long (*api_long_as_long)(PyObject *o); -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG (*api_long_as_long_long)(PyObject *o); - unsigned PY_LONG_LONG (*api_long_as_unsigned_long_long)(PyObject *o); -#else - void *api_long_as_long_long; - void *api_long_as_unsigned_long_long; -#endif - - /* - * The following are not part of the public API. - */ - void (*api_instance_destroyed_ex)(sipSimpleWrapper **sipSelfp); - - /* - * The following are part of the public API. - */ - int (*api_convert_from_slice_object)(PyObject *slice, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, - Py_ssize_t *slicelength); - size_t (*api_long_as_size_t)(PyObject *o); - void (*api_visit_wrappers)(sipWrapperVisitorFunc visitor, void *closure); - int (*api_register_exit_notifier)(PyMethodDef *md); - - /* - * The following are not part of the public API. - */ - PyObject *(*api_is_py_method_12_8)(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper **sipSelfp, const char *cname, const char *mname); -} sipAPIDef; - -const sipAPIDef *sip_init_library(PyObject *mod_dict); - - -/* - * The API implementing the optional Qt support. - */ -typedef struct _sipQtAPI { - sipTypeDef **qt_qobject; - void *(*qt_create_universal_signal)(void *, const char **); - void *(*qt_find_universal_signal)(void *, const char **); - void *(*qt_create_universal_slot)(struct _sipWrapper *, const char *, - PyObject *, const char *, const char **, int); - void (*qt_destroy_universal_slot)(void *); - void *(*qt_find_slot)(void *, const char *, PyObject *, const char *, - const char **); - int (*qt_connect)(void *, const char *, void *, const char *, int); - int (*qt_disconnect)(void *, const char *, void *, const char *); - int (*qt_same_name)(const char *, const char *); - sipSlot *(*qt_find_sipslot)(void *, void **); - int (*qt_emit_signal)(PyObject *, const char *, PyObject *); - int (*qt_connect_py_signal)(PyObject *, const char *, PyObject *, - const char *); - void (*qt_disconnect_py_signal)(PyObject *, const char *, PyObject *, - const char *); -} sipQtAPI; - - -/* - * These are flags that can be passed to sipCanConvertToType(), - * sipConvertToType() and sipForceConvertToType(). - */ -#define SIP_NOT_NONE 0x01 /* Disallow None. */ -#define SIP_NO_CONVERTORS 0x02 /* Disable any type converters. */ - - -/* - * These are flags that can be passed to sipConvertToArray(). These are held - * in sw_flags. - */ -#define SIP_READ_ONLY 0x01 /* The array is read-only. */ -#define SIP_OWNS_MEMORY 0x02 /* The array owns its memory. */ - - -/* - * These are the state flags returned by %ConvertToTypeCode. Note that the - * values share the same "flagspace" as the contents of sw_flags. - */ -#define SIP_TEMPORARY 0x01 /* A temporary instance. */ -#define SIP_DERIVED_CLASS 0x02 /* The instance is derived. */ - - -/* - * These flags are specific to the Qt support API. - */ -#define SIP_SINGLE_SHOT 0x01 /* The connection is single shot. */ - - -/* - * Useful macros, not part of the public API. - */ - -/* These are held in sw_flags. */ -#define SIP_INDIRECT 0x0004 /* If there is a level of indirection. */ -#define SIP_ACCFUNC 0x0008 /* If there is an access function. */ -#define SIP_NOT_IN_MAP 0x0010 /* If Python object is not in the map. */ - -#if !defined(Py_LIMITED_API) -#define SIP_PY_OWNED 0x0020 /* If owned by Python. */ -#define SIP_SHARE_MAP 0x0040 /* If the map slot might be occupied. */ -#define SIP_CPP_HAS_REF 0x0080 /* If C/C++ has a reference. */ -#define SIP_POSSIBLE_PROXY 0x0100 /* If there might be a proxy slot. */ -#define SIP_ALIAS 0x0200 /* If it is an alias. */ -#define SIP_CREATED 0x0400 /* If the C/C++ object has been created. */ - -#define sipIsDerived(sw) ((sw)->sw_flags & SIP_DERIVED_CLASS) -#define sipIsIndirect(sw) ((sw)->sw_flags & SIP_INDIRECT) -#define sipIsAccessFunc(sw) ((sw)->sw_flags & SIP_ACCFUNC) -#define sipNotInMap(sw) ((sw)->sw_flags & SIP_NOT_IN_MAP) -#define sipSetNotInMap(sw) ((sw)->sw_flags |= SIP_NOT_IN_MAP) -#define sipIsPyOwned(sw) ((sw)->sw_flags & SIP_PY_OWNED) -#define sipSetPyOwned(sw) ((sw)->sw_flags |= SIP_PY_OWNED) -#define sipResetPyOwned(sw) ((sw)->sw_flags &= ~SIP_PY_OWNED) -#define sipCppHasRef(sw) ((sw)->sw_flags & SIP_CPP_HAS_REF) -#define sipSetCppHasRef(sw) ((sw)->sw_flags |= SIP_CPP_HAS_REF) -#define sipResetCppHasRef(sw) ((sw)->sw_flags &= ~SIP_CPP_HAS_REF) -#define sipPossibleProxy(sw) ((sw)->sw_flags & SIP_POSSIBLE_PROXY) -#define sipSetPossibleProxy(sw) ((sw)->sw_flags |= SIP_POSSIBLE_PROXY) -#define sipIsAlias(sw) ((sw)->sw_flags & SIP_ALIAS) -#define sipWasCreated(sw) ((sw)->sw_flags & SIP_CREATED) -#endif - -#define SIP_TYPE_TYPE_MASK 0x0007 /* The type type mask. */ -#define SIP_TYPE_CLASS 0x0000 /* If the type is a C++ class. */ -#define SIP_TYPE_NAMESPACE 0x0001 /* If the type is a C++ namespace. */ -#define SIP_TYPE_MAPPED 0x0002 /* If the type is a mapped type. */ -#define SIP_TYPE_ENUM 0x0003 /* If the type is a named enum. */ -#define SIP_TYPE_SCOPED_ENUM 0x0004 /* If the type is a scoped enum. */ -#define SIP_TYPE_ABSTRACT 0x0008 /* If the type is abstract. */ -#define SIP_TYPE_SCC 0x0010 /* If the type is subject to sub-class converters. */ -#define SIP_TYPE_ALLOW_NONE 0x0020 /* If the type can handle None. */ -#define SIP_TYPE_STUB 0x0040 /* If the type is a stub. */ -#define SIP_TYPE_NONLAZY 0x0080 /* If the type has a non-lazy method. */ -#define SIP_TYPE_SUPER_INIT 0x0100 /* If the instance's super init should be called. */ -#define SIP_TYPE_LIMITED_API 0x0200 /* Use the limited API. If this is more generally required it may need to be moved to the module definition. */ - - -/* - * The following are part of the public API. - */ -#define sipTypeIsClass(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_CLASS) -#define sipTypeIsNamespace(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_NAMESPACE) -#define sipTypeIsMapped(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_MAPPED) -#define sipTypeIsEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_ENUM) -#define sipTypeIsScopedEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_SCOPED_ENUM) -#define sipTypeAsPyTypeObject(td) ((td)->td_py_type) -#define sipTypeName(td) sipNameFromPool((td)->td_module, (td)->td_cname) -#define sipTypePluginData(td) ((td)->td_plugin_data) - - -/* - * Remove in v5.1. - */ -#define sipClassName(w) PyString_FromString(Py_TYPE(w)->tp_name) -#define sipIsExactWrappedType(wt) (sipTypeAsPyTypeObject((wt)->wt_td) == (PyTypeObject *)(wt)) - - -/* - * The following are not part of the public API. - */ -#define sipTypeIsAbstract(td) ((td)->td_flags & SIP_TYPE_ABSTRACT) -#define sipTypeHasSCC(td) ((td)->td_flags & SIP_TYPE_SCC) -#define sipTypeAllowNone(td) ((td)->td_flags & SIP_TYPE_ALLOW_NONE) -#define sipTypeIsStub(td) ((td)->td_flags & SIP_TYPE_STUB) -#define sipTypeSetStub(td) ((td)->td_flags |= SIP_TYPE_STUB) -#define sipTypeHasNonlazyMethod(td) ((td)->td_flags & SIP_TYPE_NONLAZY) -#define sipTypeCallSuperInit(td) ((td)->td_flags & SIP_TYPE_SUPER_INIT) -#define sipTypeUseLimitedAPI(td) ((td)->td_flags & SIP_TYPE_LIMITED_API) - -/* - * Get various names from the string pool for various data types. - */ -#define sipNameFromPool(em, mr) (&((em)->em_strings)[(mr)]) -#define sipNameOfModule(em) sipNameFromPool((em), (em)->em_name) -#define sipPyNameOfContainer(cod, td) sipNameFromPool((td)->td_module, (cod)->cod_name) -#define sipPyNameOfEnum(etd) sipNameFromPool((etd)->etd_base.td_module, (etd)->etd_name) - - -/* - * The following are PyQt4-specific extensions. In SIP v5 they will be pushed - * out to a plugin supplied by PyQt4. - */ - -/* - * The description of a Qt signal for PyQt4. - */ -typedef struct _pyqt4QtSignal { - /* The C++ name and signature of the signal. */ - const char *signature; - - /* The optional docstring. */ - const char *docstring; - - /* - * If the signal is an overload of regular methods then this points to the - * code that implements those methods. - */ - PyMethodDef *non_signals; - - /* - * The hack to apply when built against Qt5: - * - * 0 - no hack - * 1 - add an optional None - * 2 - add an optional [] - * 3 - add an optional False - */ - int hack; -} pyqt4QtSignal; - - -/* - * This is the PyQt4-specific extension to the generated class type structure. - */ -typedef struct _pyqt4ClassPluginDef { - /* A pointer to the QObject sub-class's staticMetaObject class variable. */ - const void *static_metaobject; - - /* - * A set of flags. At the moment only bit 0 is used to say if the type is - * derived from QFlags. - */ - unsigned flags; - - /* - * The table of signals emitted by the type. These are grouped by signal - * name. - */ - const pyqt4QtSignal *qt_signals; -} pyqt4ClassPluginDef; - - -/* - * The following are PyQt5-specific extensions. In SIP v5 they will be pushed - * out to a plugin supplied by PyQt5. - */ - -/* - * The description of a Qt signal for PyQt5. - */ -typedef int (*pyqt5EmitFunc)(void *, PyObject *); - -typedef struct _pyqt5QtSignal { - /* The normalised C++ name and signature of the signal. */ - const char *signature; - - /* The optional docstring. */ - const char *docstring; - - /* - * If the signal is an overload of regular methods then this points to the - * code that implements those methods. - */ - PyMethodDef *non_signals; - - /* - * If the signal has optional arguments then this function will implement - * emit() for the signal. - */ - pyqt5EmitFunc emitter; -} pyqt5QtSignal; - - -/* - * This is the PyQt5-specific extension to the generated class type structure. - */ -typedef struct _pyqt5ClassPluginDef { - /* A pointer to the QObject sub-class's staticMetaObject class variable. */ - const void *static_metaobject; - - /* - * A set of flags. At the moment only bit 0 is used to say if the type is - * derived from QFlags. - */ - unsigned flags; - - /* - * The table of signals emitted by the type. These are grouped by signal - * name. - */ - const pyqt5QtSignal *qt_signals; - - /* The name of the interface that the class defines. */ - const char *qt_interface; -} pyqt5ClassPluginDef; - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/sip/siplib/sipint.h b/sip/siplib/sipint.h deleted file mode 100644 index d87c7814..00000000 --- a/sip/siplib/sipint.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * This file defines the SIP library internal interfaces. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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. - */ - - -#ifndef _SIPINT_H -#define _SIPINT_H - - -#include - -#include "sip.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -#undef TRUE -#define TRUE 1 - -#undef FALSE -#define FALSE 0 - - -/* - * This defines a single entry in an object map's hash table. - */ -typedef struct -{ - void *key; /* The C/C++ address. */ - sipSimpleWrapper *first; /* The first object at this address. */ -} sipHashEntry; - - -/* - * This defines the interface to a hash table class for mapping C/C++ addresses - * to the corresponding wrapped Python object. - */ -typedef struct -{ - int primeIdx; /* Index into table sizes. */ - unsigned long size; /* Size of hash table. */ - unsigned long unused; /* Nr. unused in hash table. */ - unsigned long stale; /* Nr. stale in hash table. */ - sipHashEntry *hash_array; /* Current hash table. */ -} sipObjectMap; - - -/* - * Support for the descriptors. - */ -extern PyTypeObject sipMethodDescr_Type; -PyObject *sipMethodDescr_New(PyMethodDef *pmd); -PyObject *sipMethodDescr_Copy(PyObject *orig, PyObject *mixin_name); - -extern PyTypeObject sipVariableDescr_Type; -PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td, - const sipContainerDef *cod); -PyObject *sipVariableDescr_Copy(PyObject *orig, PyObject *mixin_name); - - -/* - * Support for API versions. - */ -PyObject *sipGetAPI(PyObject *self, PyObject *args); -PyObject *sipSetAPI(PyObject *self, PyObject *args); -int sip_api_is_api_enabled(const char *name, int from, int to); -int sipIsRangeEnabled(sipExportedModuleDef *em, int range_index); -int sipInitAPI(sipExportedModuleDef *em, PyObject *mod_dict); - - -/* - * Support for void pointers. - */ -extern PyTypeObject sipVoidPtr_Type; -void *sip_api_convert_to_void_ptr(PyObject *obj); -PyObject *sip_api_convert_from_void_ptr(void *val); -PyObject *sip_api_convert_from_const_void_ptr(const void *val); -PyObject *sip_api_convert_from_void_ptr_and_size(void *val, Py_ssize_t size); -PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val, - Py_ssize_t size); - - -/* - * Support for int converters. - */ -PyObject *sipEnableOverflowChecking(PyObject *self, PyObject *args); -int sip_api_enable_overflow_checking(int enable); -int sip_api_convert_to_bool(PyObject *o); -char sip_api_long_as_char(PyObject *o); -signed char sip_api_long_as_signed_char(PyObject *o); -unsigned char sip_api_long_as_unsigned_char(PyObject *o); -short sip_api_long_as_short(PyObject *o); -unsigned short sip_api_long_as_unsigned_short(PyObject *o); -int sip_api_long_as_int(PyObject *o); -unsigned int sip_api_long_as_unsigned_int(PyObject *o); -long sip_api_long_as_long(PyObject *o); -unsigned long sip_api_long_as_unsigned_long(PyObject *o); -#if defined(HAVE_LONG_LONG) -PY_LONG_LONG sip_api_long_as_long_long(PyObject *o); -unsigned PY_LONG_LONG sip_api_long_as_unsigned_long_long(PyObject *o); -#endif -size_t sip_api_long_as_size_t(PyObject *o); - - -extern sipQtAPI *sipQtSupport; /* The Qt support API. */ -extern sipWrapperType sipSimpleWrapper_Type; /* The simple wrapper type. */ -extern sipTypeDef *sipQObjectType; /* The QObject type. */ - -void *sipGetRx(sipSimpleWrapper *txSelf, const char *sigargs, PyObject *rxObj, - const char *slot, const char **memberp); -PyObject *sip_api_connect_rx(PyObject *txObj, const char *sig, PyObject *rxObj, - const char *slot, int type); -PyObject *sip_api_disconnect_rx(PyObject *txObj, const char *sig, - PyObject *rxObj,const char *slot); - - -/* - * These are part of the SIP API but are also used within the SIP module. - */ -void *sip_api_malloc(size_t nbytes); -void sip_api_free(void *mem); -void *sip_api_get_address(sipSimpleWrapper *w); -void *sip_api_get_cpp_ptr(sipSimpleWrapper *w, const sipTypeDef *td); -PyObject *sip_api_convert_from_type(void *cppPtr, const sipTypeDef *td, - PyObject *transferObj); -void sip_api_instance_destroyed(sipSimpleWrapper *sipSelf); -void sip_api_end_thread(void); -void *sip_api_force_convert_to_type(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp); -void sip_api_free_sipslot(sipSlot *slot); -int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot); -PyObject *sip_api_invoke_slot(const sipSlot *slot, PyObject *sigargs); -PyObject *sip_api_invoke_slot_ex(const sipSlot *slot, PyObject *sigargs, - int no_receiver_check); -void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp, int flags); -int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot); -int sip_api_convert_from_slice_object(PyObject *slice, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, - Py_ssize_t *slicelength); -int sip_api_deprecated(const char *classname, const char *method); - - -/* - * These are not part of the SIP API but are used within the SIP module. - */ -sipClassTypeDef *sipGetGeneratedClassType(const sipEncodedTypeDef *enc, - const sipClassTypeDef *ctd); -void sipSaveMethod(sipPyMethod *pm,PyObject *meth); -int sipGetPending(void **pp, sipWrapper **op, int *fp); -int sipIsPending(void); -PyObject *sipWrapInstance(void *cpp, PyTypeObject *py_type, PyObject *args, - sipWrapper *owner, int flags); -void *sipConvertRxEx(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp, int flags); - -void sipOMInit(sipObjectMap *om); -void sipOMFinalise(sipObjectMap *om); -sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, - const sipTypeDef *td); -void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val); -int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val); - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define sipSetBool(p, v) (*(_Bool *)(p) = (v)) -#endif - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/sip/siplib/siplib.c b/sip/siplib/siplib.c deleted file mode 100644 index 974464ee..00000000 --- a/sip/siplib/siplib.c +++ /dev/null @@ -1,13281 +0,0 @@ -/* - * SIP library code. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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 -#include -#include - -#include -#include -#include -#include -#include - -#include "sip.h" -#include "sipint.h" -#include "array.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 accommodate the extra information - * we associate with a wrapped type. - */ - -static PyObject *sipWrapperType_alloc(PyTypeObject *self, Py_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_as_async (Python v3.5), 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 */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* - * 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_as_async (Python v3.5), 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 */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif - }, - { - 0, /* am_await */ - 0, /* am_aiter */ - 0, /* am_anext */ - }, - { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - 0, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - 0, /* nb_index */ - 0, /* nb_matrix_multiply */ - 0, /* nb_inplace_matrix_multiply */ - }, - { - 0, /* mp_length */ - 0, /* mp_subscript */ - 0, /* mp_ass_subscript */ - }, - { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* was_sq_slice */ - 0, /* sq_ass_item */ - 0, /* was_sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ - }, - { - 0, /* bf_getbuffer */ - 0, /* bf_releasebuffer */ - }, - 0, /* ht_name */ - 0, /* ht_slots */ - 0, /* ht_qualname */ - 0, /* ht_cached_keys */ -#if PY_VERSION_HEX >= 0x03090000 - 0, /* ht_module */ -#endif -#if !defined(STACKLESS) - }, -#endif - 0, /* wt_user_type */ - 0, /* wt_dict_complete */ - 0, /* wt_unused */ - 0, /* wt_td */ - 0, /* wt_iextend */ - 0, /* wt_new_user_type_handler */ - 0, /* wt_user_data */ -}; - - -static void sip_api_bad_catcher_result(PyObject *method); -static void sip_api_bad_length_for_slice(Py_ssize_t seqlen, - Py_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 void sip_api_call_procedure_method(sip_gilstate_t gil_state, - sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, - PyObject *method, const char *fmt, ...); -static Py_ssize_t sip_api_convert_from_sequence_index(Py_ssize_t idx, - Py_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 int sip_api_can_convert_to_enum(PyObject *pyObj, const sipTypeDef *td); -static int sip_api_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 PyObject *sip_api_convert_from_new_pytype(void *cpp, - PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, - const char *fmt, ...); -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_ex(sip_gilstate_t gil_state, - sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, - PyObject *method, PyObject *res, const char *fmt, ...); -static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res, - const char *fmt, ...); -static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, - sipSimpleWrapper *py_self, sip_gilstate_t gil_state); -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 PyObject *sip_api_is_py_method_12_8(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper **sipSelfp, 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 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_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 PyObject *sip_api_get_reference(PyObject *self, int key); -static int sip_api_is_owned_by_python(sipSimpleWrapper *sw); -static int sip_api_is_derived_class(sipSimpleWrapper *sw); -static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp); -static void sip_api_set_destroy_on_exit(int value); -static int sip_api_enable_autoconversion(const sipTypeDef *td, int enable); -static int sip_api_init_mixin(PyObject *self, PyObject *args, PyObject *kwds, - const sipClassTypeDef *ctd); -static void *sip_api_get_mixin_address(sipSimpleWrapper *w, - const sipTypeDef *td); -static int sip_api_register_proxy_resolver(const sipTypeDef *td, - sipProxyResolverFunc resolver); -static PyInterpreterState *sip_api_get_interpreter(void); -static sipNewUserTypeFunc sip_api_set_new_user_type_handler( - const sipTypeDef *td, sipNewUserTypeFunc handler); -static void sip_api_set_type_user_data(sipWrapperType *wt, void *data); -static void *sip_api_get_type_user_data(const sipWrapperType *wt); -static PyObject *sip_api_py_type_dict(const PyTypeObject *py_type); -static const char *sip_api_py_type_name(const PyTypeObject *py_type); -static int sip_api_get_method(PyObject *obj, sipMethodDef *method); -static PyObject *sip_api_from_method(const sipMethodDef *method); -static int sip_api_get_c_function(PyObject *obj, sipCFunctionDef *c_function); -static int sip_api_get_date(PyObject *obj, sipDateDef *date); -static PyObject *sip_api_from_date(const sipDateDef *date); -static int sip_api_get_datetime(PyObject *obj, sipDateDef *date, - sipTimeDef *time); -static PyObject *sip_api_from_datetime(const sipDateDef *date, - const sipTimeDef *time); -static int sip_api_get_time(PyObject *obj, sipTimeDef *time); -static PyObject *sip_api_from_time(const sipTimeDef *time); -static int sip_api_is_user_type(const sipWrapperType *wt); -static struct _frame *sip_api_get_frame(int); -static int sip_api_check_plugin_for_type(const sipTypeDef *td, - const char *name); -static PyObject *sip_api_unicode_new(Py_ssize_t len, unsigned maxchar, - int *kind, void **data); -static void sip_api_unicode_write(int kind, void *data, int index, - unsigned value); -static void *sip_api_unicode_data(PyObject *obj, int *char_size, - Py_ssize_t *len); -static int sip_api_get_buffer_info(PyObject *obj, sipBufferInfoDef *bi); -static void sip_api_release_buffer_info(sipBufferInfoDef *bi); -static PyObject *sip_api_get_user_object(const sipSimpleWrapper *sw); -static void sip_api_set_user_object(sipSimpleWrapper *sw, PyObject *user); -static int sip_api_enable_gc(int enable); -static void sip_api_print_object(PyObject *o); -static int sip_api_register_event_handler(sipEventType type, - const sipTypeDef *td, void *handler); -static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp); -static void sip_api_visit_wrappers(sipWrapperVisitorFunc visitor, - void *closure); -static int sip_api_register_exit_notifier(PyMethodDef *md); - - -/* - * 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_call_procedure_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, - sip_api_get_address, - sip_api_set_destroy_on_exit, - sip_api_enable_autoconversion, - sip_api_get_mixin_address, - sip_api_convert_from_new_pytype, - sip_api_convert_to_typed_array, - sip_api_convert_to_array, - sip_api_register_proxy_resolver, - sip_api_get_interpreter, - sip_api_set_new_user_type_handler, - sip_api_set_type_user_data, - sip_api_get_type_user_data, - sip_api_py_type_dict, - sip_api_py_type_name, - sip_api_get_method, - sip_api_from_method, - sip_api_get_c_function, - sip_api_get_date, - sip_api_from_date, - sip_api_get_datetime, - sip_api_from_datetime, - sip_api_get_time, - sip_api_from_time, - sip_api_is_user_type, - sip_api_get_frame, - sip_api_check_plugin_for_type, - sip_api_unicode_new, - sip_api_unicode_write, - sip_api_unicode_data, - sip_api_get_buffer_info, - sip_api_release_buffer_info, - sip_api_get_user_object, - sip_api_set_user_object, - /* - * The following are not part of the public API. - */ - sip_api_init_module, - sip_api_parse_args, - sip_api_parse_pair, - /* - * The following are part of the public API. - */ - sip_api_instance_destroyed, - /* - * The following are not part of the public API. - */ - 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_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, - sip_api_parse_result_ex, - sip_api_call_error_handler, - sip_api_init_mixin, - sip_api_get_reference, - /* - * The following are part of the public API. - */ - sip_api_is_owned_by_python, - /* - * The following are not part of the public API. - */ - sip_api_is_derived_class, - /* - * The following may be used by Qt 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_invoke_slot_ex, - sip_api_save_slot, - sip_api_clear_any_slot_reference, - sip_api_visit_slot, - /* - * 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 are part of the public API. - */ - sip_api_enable_gc, - sip_api_print_object, - sip_api_register_event_handler, - sip_api_convert_to_enum, - sip_api_convert_to_bool, - sip_api_enable_overflow_checking, - sip_api_long_as_char, - sip_api_long_as_signed_char, - sip_api_long_as_unsigned_char, - sip_api_long_as_short, - sip_api_long_as_unsigned_short, - sip_api_long_as_int, - sip_api_long_as_unsigned_int, - sip_api_long_as_long, -#if defined(HAVE_LONG_LONG) - sip_api_long_as_long_long, - sip_api_long_as_unsigned_long_long, -#else - 0, - 0, -#endif - /* - * The following are not part of the public API. - */ - sip_api_instance_destroyed_ex, - /* - * The following are part of the public API. - */ - sip_api_convert_from_slice_object, - sip_api_long_as_size_t, - sip_api_visit_wrappers, - sip_api_register_exit_notifier, - /* - * The following are not part of the public API. - */ - sip_api_is_py_method_12_8, -}; - - -#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 converters. */ -#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, Overflow -} 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. */ - int overflow_arg_nr; /* The overflowed positional argument. */ - const char *overflow_arg_name; /* The overflowed 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; - - -/* - * An entry in the linked list of proxy resolvers. - */ -typedef struct _sipProxyResolver { - const sipTypeDef *td; /* The type the resolver handles. */ - sipProxyResolverFunc resolver; /* The resolver. */ - struct _sipProxyResolver *next; /* The next in the list. */ -} sipProxyResolver; - - -/* - * An entry in the linked list of event handlers. - */ -typedef struct _sipEventHandler { - const sipClassTypeDef *ctd; /* The type the handler handles. */ - void *handler; /* The handler. */ - struct _sipEventHandler *next; /* The next in the list. */ -} sipEventHandler; - - -/***************************************************************************** - * The structures to support a Python type to hold a named enum. - *****************************************************************************/ - -static PyObject *sipEnumType_alloc(PyTypeObject *self, Py_ssize_t nitems); -static PyObject *sipEnumType_getattro(PyObject *self, PyObject *name); - - -/* - * The type data structure. We inherit everything from the standard Python - * metatype and the size of the type object created is increased to accommodate - * 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_as_async (Python v3.5), 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 */ - sipEnumType_getattro, /* 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 */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* - * Remove these in SIP v5. - */ -sipQtAPI *sipQtSupport = NULL; -sipTypeDef *sipQObjectType; - -static int got_kw_handler = FALSE; -static int (*kw_handler)(PyObject *, void *, PyObject *); - - -/* - * 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 **unused_backdoor = NULL; /* For passing dict of unused arguments. */ - -static PyObject *init_name = NULL; /* '__init__'. */ -static PyObject *empty_tuple; /* The empty tuple. */ -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 sipProxyResolver *proxyResolvers = NULL; /* The list of proxy resolvers. */ -static sipPyObject *sipRegisteredPyTypes = NULL; /* Registered Python types. */ -static sipPyObject *sipDisabledAutoconversions = NULL; /* Python types whose auto-conversion is disabled. */ -static PyInterpreterState *sipInterpreter = NULL; /* The interpreter. */ -static int destroy_on_exit = TRUE; /* Destroy owned objects on exit. */ -static sipEventHandler *event_handlers[sipEventNrEvents]; /* The event handler lists. */ - -static void addClassSlots(sipWrapperType *wt, const sipClassTypeDef *ctd); -static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots); -static void *findSlot(PyObject *self, sipPySlotType st); -static void *findSlotInClass(const sipClassTypeDef *psd, sipPySlotType st); -static void *findSlotInSlotList(sipPySlotDef *psd, sipPySlotType st); -static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2, - sipPySlotType st); -static int ssizeobjargprocSlot(PyObject *self, Py_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 int parseResult(PyObject *method, PyObject *res, - sipSimpleWrapper *py_self, const char *fmt, va_list va); -static PyObject *signature_FromDocstring(const char *doc, Py_ssize_t line); -static PyObject *detail_FromFailure(PyObject *failure_obj); -static int isQObject(PyObject *obj); -static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td); -static int convertFromSequence(PyObject *seq, const sipTypeDef *td, - void **array, Py_ssize_t *nr_elem); -static PyObject *convertToSequence(void *array, Py_ssize_t nr_elem, - const sipTypeDef *td); -static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr, - sipSimpleWrapper **selfp); -static int compareTypedefName(const void *key, const void *el); -static int checkPointer(void *ptr, sipSimpleWrapper *sw); -static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type, - const sipTypeDef *dst_type); -static void finalise(void); -static PyObject *getDefaultBase(void); -static PyObject *getDefaultSimpleBase(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, - PyObject *type_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 *args); -static PyObject *unpickle_type(PyObject *obj, PyObject *args); -static PyObject *pickle_enum(PyObject *obj, PyObject *args); -static PyObject *unpickle_enum(PyObject *obj, PyObject *args); -static int setReduce(PyTypeObject *type, PyMethodDef *pickler); -static int createEnum(sipExportedModuleDef *client, sipEnumTypeDef *etd, - int enum_nr, PyObject *mod_dict); -static PyObject *createUnscopedEnum(sipExportedModuleDef *client, - sipEnumTypeDef *etd, PyObject *name); -static PyObject *createScopedEnum(sipExportedModuleDef *client, - sipEnumTypeDef *etd, int enum_nr, PyObject *name); -static PyObject *createTypeDict(sipExportedModuleDef *em); -static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, - sipExportedModuleDef *em); -static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr); -static int convertPass(const sipTypeDef **tdp, 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 *assign(PyObject *self, PyObject *args); -static PyObject *cast(PyObject *self, PyObject *args); -static PyObject *callDtor(PyObject *self, PyObject *args); -static PyObject *dumpWrapper(PyObject *self, PyObject *arg); -static PyObject *enableAutoconversion(PyObject *self, PyObject *args); -static PyObject *isDeleted(PyObject *self, PyObject *args); -static PyObject *isPyCreated(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 PyObject *setDestroyOnExit(PyObject *self, PyObject *args); -static void clear_wrapper(sipSimpleWrapper *sw); -static void print_object(const char *label, PyObject *obj); -static void addToParent(sipWrapper *self, sipWrapper *owner); -static void removeFromParent(sipWrapper *self); -static void detachChildren(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, - Py_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, Py_ssize_t *aszp); -static int convertToWCharArray(PyObject *obj, wchar_t **ap, Py_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); -static void *explicit_access_func(sipSimpleWrapper *sw, AccessFuncOp op); -static void *indirect_access_func(sipSimpleWrapper *sw, AccessFuncOp op); -static void clear_access_func(sipSimpleWrapper *sw); -static int check_encoded_string(PyObject *obj); -static int isNonlazyMethod(PyMethodDef *pmd); -static int addMethod(PyObject *dict, PyMethodDef *pmd); -static PyObject *create_property(sipVariableDef *vd); -static PyObject *create_function(PyMethodDef *ml); -static PyObject *sip_exit(PyObject *self, PyObject *args); -static sipConvertFromFunc get_from_convertor(const sipTypeDef *td); -static sipPyObject **autoconversion_disabled(const sipTypeDef *td); -static void fix_slots(PyTypeObject *py_type, sipPySlotDef *psd); -static sipFinalFunc find_finalisation(sipClassTypeDef *ctd); -static sipNewUserTypeFunc find_new_user_type_handler(sipWrapperType *wt); -static PyObject *next_in_mro(PyObject *self, PyObject *after); -static int super_init(PyObject *self, PyObject *args, PyObject *kwds, - PyObject *type); -static sipSimpleWrapper *deref_mixin(sipSimpleWrapper *w); -static PyObject *wrap_simple_instance(void *cpp, const sipTypeDef *td, - sipWrapper *owner, int flags); -static void *resolve_proxy(const sipTypeDef *td, void *proxy); -static PyObject *call_method(PyObject *method, const char *fmt, va_list va); -static int importTypes(sipExportedModuleDef *client, sipImportedModuleDef *im, - sipExportedModuleDef *em); -static int importErrorHandlers(sipExportedModuleDef *client, - sipImportedModuleDef *im, sipExportedModuleDef *em); -static int importExceptions(sipExportedModuleDef *client, - sipImportedModuleDef *im, sipExportedModuleDef *em); -static int is_subtype(const sipClassTypeDef *ctd, - const sipClassTypeDef *base_ctd); -static PyObject *import_module_attr(const char *module, const char *attr); -static const sipContainerDef *get_container(const sipTypeDef *td); -static PyObject *get_qualname(const sipTypeDef *td, PyObject *name); -static int convert_to_enum(PyObject *obj, const sipTypeDef *td, int allow_int); -static void handle_failed_int_conversion(sipParseFailure *pf, PyObject *arg); -static void enum_expected(PyObject *obj, const sipTypeDef *td); -static int long_as_nonoverflow_int(PyObject *val_obj); -static int dict_set_and_discard(PyObject *dict, const char *name, - PyObject *obj); - - -/* - * Initialise the module as a library. - */ -const sipAPIDef *sip_init_library(PyObject *mod_dict) -{ - static PyMethodDef methods[] = { - /* This must be first. */ - {"_unpickle_enum", unpickle_enum, METH_VARARGS, NULL}, - /* This must be second. */ - {"_unpickle_type", unpickle_type, METH_VARARGS, NULL}, - {"assign", assign, METH_VARARGS, NULL}, - {"cast", cast, METH_VARARGS, NULL}, - {"delete", callDtor, METH_VARARGS, NULL}, - {"dump", dumpWrapper, METH_O, NULL}, - {"enableautoconversion", enableAutoconversion, METH_VARARGS, NULL}, - {"enableoverflowchecking", sipEnableOverflowChecking, METH_VARARGS, NULL}, - {"getapi", sipGetAPI, METH_VARARGS, NULL}, - {"isdeleted", isDeleted, METH_VARARGS, NULL}, - {"ispycreated", isPyCreated, METH_VARARGS, NULL}, - {"ispyowned", isPyOwned, METH_VARARGS, NULL}, - {"setapi", sipSetAPI, METH_VARARGS, NULL}, - {"setdeleted", setDeleted, METH_VARARGS, NULL}, - {"setdestroyonexit", setDestroyOnExit, 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}, - {NULL, NULL, 0, NULL} - }; - - static PyMethodDef sip_exit_md = { - "_sip_exit", sip_exit, METH_NOARGS, NULL - }; - - PyObject *obj; - PyMethodDef *md; - - /* - * Remind ourselves to add support for capsule variables when we have - * another reason to move to the next major version number. - */ -#if SIP_API_MAJOR_NR > 12 -#error "Add support for capsule variables" -#endif - -#if PY_VERSION_HEX < 0x03070000 && defined(WITH_THREAD) - PyEval_InitThreads(); -#endif - - /* Add the SIP version number. */ - obj = PyLong_FromLong(SIP_VERSION); - - if (dict_set_and_discard(mod_dict, "SIP_VERSION", obj) < 0) - return NULL; - - obj = PyUnicode_FromString(SIP_VERSION_STR); - - if (dict_set_and_discard(mod_dict, "SIP_VERSION_STR", obj) < 0) - return NULL; - - /* Add the methods. */ - for (md = methods; md->ml_name != NULL; ++md) - { - PyObject *meth = PyCFunction_New(md, NULL); - - if (dict_set_and_discard(mod_dict, md->ml_name, meth) < 0) - return NULL; - - if (md == &methods[0]) - { - Py_INCREF(meth); - enum_unpickler = meth; - } - else if (md == &methods[1]) - { - Py_INCREF(meth); - type_unpickler = meth; - } - } - - /* Initialise the types. */ - sipWrapperType_Type.tp_base = &PyType_Type; - - if (PyType_Ready(&sipWrapperType_Type) < 0) - return NULL; - - if (PyType_Ready((PyTypeObject *)&sipSimpleWrapper_Type) < 0) - return NULL; - - if (sip_api_register_py_type((PyTypeObject *)&sipSimpleWrapper_Type) < 0) - return NULL; - -#if defined(STACKLESS) - sipWrapper_Type.super.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type; -#else - sipWrapper_Type.super.ht_type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type; -#endif - - if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0) - return NULL; - - if (PyType_Ready(&sipMethodDescr_Type) < 0) - return NULL; - - if (PyType_Ready(&sipVariableDescr_Type) < 0) - return NULL; - - sipEnumType_Type.tp_base = &PyType_Type; - - if (PyType_Ready(&sipEnumType_Type) < 0) - return NULL; - - if (PyType_Ready(&sipVoidPtr_Type) < 0) - return NULL; - - if (PyType_Ready(&sipArray_Type) < 0) - return NULL; - - /* Add the public types. */ - if (PyDict_SetItemString(mod_dict, "wrappertype", (PyObject *)&sipWrapperType_Type) < 0) - return NULL; - - if (PyDict_SetItemString(mod_dict, "simplewrapper", (PyObject *)&sipSimpleWrapper_Type) < 0) - return NULL; - - if (PyDict_SetItemString(mod_dict, "wrapper", (PyObject *)&sipWrapper_Type) < 0) - return NULL; - - if (PyDict_SetItemString(mod_dict, "voidptr", (PyObject *)&sipVoidPtr_Type) < 0) - return NULL; - - /* These will always be needed. */ - if (objectify("__init__", &init_name) < 0) - return NULL; - - if ((empty_tuple = PyTuple_New(0)) == NULL) - return NULL; - - /* Initialise the object map. */ - sipOMInit(&cppPyMap); - - /* Make sure we are notified at the end of the exit process. */ - if (Py_AtExit(finalise) < 0) - return NULL; - - /* Make sure we are notified at the start of the exit process. */ - if (sip_api_register_exit_notifier(&sip_exit_md) < 0) - return NULL; - - /* - * Get the current interpreter. This will be shared between all threads. - */ - sipInterpreter = PyThreadState_Get()->interp; - - return &sip_api; -} - - -/* - * Set a dictionary item and discard the reference to the item even if there - * was an error. - */ -static int dict_set_and_discard(PyObject *dict, const char *name, PyObject *obj) -{ - int rc; - - if (obj == NULL) - return -1; - - rc = PyDict_SetItemString(dict, name, obj); - - Py_DECREF(obj); - - return rc; -} - - -#if _SIP_MODULE_SHARED -/* - * The Python module initialisation function. - */ -#if defined(SIP_STATIC_MODULE) -PyObject *_SIP_MODULE_ENTRY(void) -#else -PyMODINIT_FUNC _SIP_MODULE_ENTRY(void) -#endif -{ - static PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - _SIP_MODULE_FQ_NAME, /* m_name */ - NULL, /* m_doc */ - -1, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ - }; - - const sipAPIDef *api; - PyObject *mod, *mod_dict, *api_obj; - - /* Create the module. */ - if ((mod = PyModule_Create(&module_def)) == NULL) - return NULL; - - mod_dict = PyModule_GetDict(mod); - - /* Initialise the module dictionary and static variables. */ - if ((api = sip_init_library(mod_dict)) == NULL) - return NULL; - - /* Publish the SIP API. */ - api_obj = PyCapsule_New((void *)api, _SIP_MODULE_FQ_NAME "._C_API", NULL); - - if (dict_set_and_discard(mod_dict, "_C_API", api_obj) < 0) - { - Py_DECREF(mod); - return NULL; - } - -#if _SIP_MODULE_LEGACY - { - /* - * Also install the package-specific module at the top level for - * backwards compatibility. - */ - PyObject *modules = PySys_GetObject("modules"); - - if (modules != NULL) - PyDict_SetItemString(modules, "sip", mod); - } -#endif - - return mod; -} -#endif - - -/* - * Return the current interpreter, if there is one. - */ -static PyInterpreterState *sip_api_get_interpreter(void) -{ - return sipInterpreter; -} - - -/* - * 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; - - (void)self; - - 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. Note that we - * use the same calling convention as sys.getrefcount() so that it has the - * same caveat regarding the reference count. - */ -static PyObject *dumpWrapper(PyObject *self, PyObject *arg) -{ - sipSimpleWrapper *sw; - - (void)self; - - if (!PyObject_TypeCheck(arg, (PyTypeObject *)&sipSimpleWrapper_Type)) - { - PyErr_Format(PyExc_TypeError, - "dump() argument 1 must be sip.simplewrapper, not %s", - Py_TYPE(arg)->tp_name); - return NULL; - } - - sw = (sipSimpleWrapper *)arg; - - print_object(NULL, (PyObject *)sw); - - printf(" Reference count: %" PY_FORMAT_SIZE_T "d\n", Py_REFCNT(sw)); - printf(" Address of wrapped object: %p\n", sip_api_get_address(sw)); - printf(" Created by: %s\n", (sipIsDerived(sw) ? "Python" : "C/C++")); - printf(" To be destroyed by: %s\n", (sipIsPyOwned(sw) ? "Python" : "C/C++")); - - 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; -} - - -/* - * 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; - - (void)self; - - if (PyArg_ParseTuple(args, "O!O:transferto", &sipWrapper_Type, &w, &owner)) - { - if (owner == Py_None) - { - /* - * Note that the Python API is different to the C API when the - * owner is 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; - - (void)self; - - if (PyArg_ParseTuple(args, "O!:transferback", &sipWrapper_Type, &w)) - { - sip_api_transfer_back(w); - - Py_INCREF(Py_None); - return Py_None; - } - - return NULL; -} - - -/* - * Invoke the assignment operator for a C++ instance. - */ -static PyObject *assign(PyObject *self, PyObject *args) -{ - sipSimpleWrapper *dst, *src; - PyTypeObject *dst_type, *src_type; - const sipTypeDef *td, *super_td; - sipAssignFunc assign_helper; - void *dst_addr, *src_addr; - - (void)self; - - if (!PyArg_ParseTuple(args, "O!O!:assign", &sipSimpleWrapper_Type, &dst, &sipSimpleWrapper_Type, &src)) - return NULL; - - /* Get the assignment helper. */ - dst_type = Py_TYPE(dst); - td = ((sipWrapperType *)dst_type)->wt_td; - - if (sipTypeIsMapped(td)) - assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign; - else - assign_helper = ((const sipClassTypeDef *)td)->ctd_assign; - - if (assign_helper == NULL) - { - PyErr_SetString(PyExc_TypeError, - "argument 1 of assign() does not support assignment"); - return NULL; - } - - /* Check the types are compatible. */ - src_type = Py_TYPE(src); - - if (src_type == dst_type) - { - super_td = NULL; - } - else if (PyType_IsSubtype(src_type, dst_type)) - { - super_td = td; - } - else - { - PyErr_SetString(PyExc_TypeError, - "type of argument 1 of assign() must be a super-type of type of argument 2"); - return NULL; - } - - /* Get the addresses. */ - if ((dst_addr = sip_api_get_cpp_ptr(dst, NULL)) == NULL) - return NULL; - - if ((src_addr = sip_api_get_cpp_ptr(src, super_td)) == NULL) - return NULL; - - /* Do the assignment. */ - assign_helper(dst_addr, 0, src_addr); - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * 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; - - (void)self; - - 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->wt_td; - else - { - PyErr_SetString(PyExc_TypeError, "argument 1 of 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 wrap_simple_instance(addr, wt->wt_td, NULL, - (sw->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; - - (void)self; - - if (!PyArg_ParseTuple(args, "O!:delete", &sipSimpleWrapper_Type, &sw)) - return NULL; - - addr = getPtrTypeDef(sw, &ctd); - - if (checkPointer(addr, sw) < 0) - return NULL; - - clear_wrapper(sw); - - release(addr, (const sipTypeDef *)ctd, sw->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; - - (void)self; - - if (!PyArg_ParseTuple(args, "O!:isdeleted", &sipSimpleWrapper_Type, &sw)) - return NULL; - - res = (sip_api_get_address(sw) == NULL ? Py_True : Py_False); - - Py_INCREF(res); - return res; -} - - -/* - * Check if an instance was created by Python. - */ -static PyObject *isPyCreated(PyObject *self, PyObject *args) -{ - sipSimpleWrapper *sw; - PyObject *res; - - (void)self; - - if (!PyArg_ParseTuple(args, "O!:ispycreated", &sipSimpleWrapper_Type, &sw)) - return NULL; - - /* sipIsDerived() is a misnomer. */ - res = (sipIsDerived(sw) ? 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; - - (void)self; - - 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; - - (void)self; - - if (!PyArg_ParseTuple(args, "O!:setdeleted", &sipSimpleWrapper_Type, &sw)) - return NULL; - - clear_wrapper(sw); - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Unwrap an instance. - */ -static PyObject *unwrapInstance(PyObject *self, PyObject *args) -{ - sipSimpleWrapper *sw; - - (void)self; - - 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 PY_LONG_LONG addr; - sipWrapperType *wt; - - (void)self; - - if (PyArg_ParseTuple(args, "KO!:wrapinstance", &addr, &sipWrapperType_Type, &wt)) - return sip_api_convert_from_type((void *)addr, wt->wt_td, NULL); - - return NULL; -} - - -/* - * Set the destroy on exit flag from Python code. - */ -static PyObject *setDestroyOnExit(PyObject *self, PyObject *args) -{ - (void)self; - - if (PyArg_ParseTuple(args, "i:setdestroyonexit", &destroy_on_exit)) - { - Py_INCREF(Py_None); - return Py_None; - } - - return NULL; -} - - -/* - * Set the destroy on exit flag from C++ code. - */ -static void sip_api_set_destroy_on_exit(int value) -{ - destroy_on_exit = value; -} - - -/* - * 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); - - (void)unused; - - /* 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; - } - - if (im->im_imported_types != NULL && importTypes(client, im, em) < 0) - return -1; - - if (im->im_imported_veh != NULL && importErrorHandlers(client, im, em) < 0) - return -1; - - if (im->im_imported_exceptions != NULL && importExceptions(client, im, em) < 0) - return -1; - - ++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 QObject. */ - if (em->em_qt_api != NULL && client->em_qt_api != NULL) - { - PyErr_Format(PyExc_RuntimeError, - "the %s and %s modules both wrap the QObject class", - full_name, sipNameOfModule(em)); - - return -1; - } - } - - /* Convert the module name to an object. */ - if ((client->em_nameobj = PyUnicode_FromString(full_name)) == NULL) - return -1; - - /* Add it to the list of client modules. */ - client->em_next = moduleList; - moduleList = client; - - /* Get any keyword handler. Remove this in SIP v5. */ - if (!got_kw_handler) - { - kw_handler = sip_api_import_symbol("pyqt_kw_handler"); - got_kw_handler = TRUE; - } - - 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) || sipTypeIsScopedEnum(td)) - { - sipEnumTypeDef *etd = (sipEnumTypeDef *)td; - - if (td->td_version < 0 || sipIsRangeEnabled(client, td->td_version)) - if (createEnum(client, etd, i, mod_dict) < 0) - return -1; - - /* - * Register the enum pickler for nested enums (non-nested enums - * don't need special treatment). - */ - if (sipTypeIsEnum(td) && 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 Qt support API. */ - if (client->em_qt_api != NULL) - { - sipQtSupport = client->em_qt_api; - sipQObjectType = *sipQtSupport->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->wt_iextend; - wt->wt_iextend = ie; - } - - ++ie; - } - } - - /* Set the base class object for any sub-class converters. */ - 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) - { - sipTypeDef *etd = client->em_types[emd->em_enum]; - PyObject *mo; - - if (sipTypeIsScopedEnum(etd)) - continue; - - mo = sip_api_convert_from_enum(emd->em_val, etd); - - if (dict_set_and_discard(mod_dict, emd->em_name, mo) < 0) - return -1; - } - - - /* - * 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. This should already have been done, - * but just in case... - */ - 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; -} - - -/* - * Convert a new C/C++ instance to a Python instance of a specific Python type.. - */ -static PyObject *sip_api_convert_from_new_pytype(void *cpp, - PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, - 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 = sipWrapInstance(cpp, py_type, args, owner, - (selfp != NULL ? SIP_DERIVED_CLASS : 0)); - - /* Initialise the rest of an instance of a derived class. */ - if (selfp != NULL) - *selfp = (sipSimpleWrapper *)res; - } - else - { - res = NULL; - } - - Py_XDECREF(args); - - va_end(va); - - return res; -} - - -/* - * Call a method and return the result. - */ -static PyObject *call_method(PyObject *method, const char *fmt, va_list va) -{ - PyObject *args, *res; - - if ((args = PyTuple_New(strlen(fmt))) == NULL) - return NULL; - - if (buildObject(args, fmt, va) != NULL) - res = PyObject_CallObject(method, args); - else - res = NULL; - - Py_DECREF(args); - - return res; -} - - -/* - * Call the Python re-implementation of a C++ virtual that does not return a - * value and handle the result.. - */ -static void sip_api_call_procedure_method(sip_gilstate_t gil_state, - sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, - PyObject *method, const char *fmt, ...) -{ - PyObject *res; - va_list va; - - va_start(va, fmt); - res = call_method(method, fmt, va); - va_end(va); - - if (res != NULL) - { - Py_DECREF(res); - - if (res != Py_None) - { - sip_api_bad_catcher_result(method); - res = NULL; - } - } - - Py_DECREF(method); - - if (res == NULL) - sip_api_call_error_handler(error_handler, py_self, gil_state); - - SIP_RELEASE_GIL(gil_state); -} - - -/* - * Call the Python re-implementation of a C++ virtual. - */ -static PyObject *sip_api_call_method(int *isErr, PyObject *method, - const char *fmt, ...) -{ - PyObject *res; - va_list va; - - va_start(va, fmt); - res = call_method(method, fmt, va); - va_end(va); - - if (res == NULL && isErr != NULL) - *isErr = TRUE; - - 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 = (int)(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; - Py_ssize_t l; - - s = va_arg(va, char *); - l = va_arg(va, Py_ssize_t); - - if (s != NULL) - { - el = PyBytes_FromStringAndSize(s, l); - } - else - { - Py_INCREF(Py_None); - el = Py_None; - } - } - - break; - - case 'G': -#if defined(HAVE_WCHAR_H) - { - wchar_t *s; - Py_ssize_t l; - - s = va_arg(va, wchar_t *); - l = va_arg(va, Py_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 = PyBytes_FromStringAndSize(&c, 1); - } - - break; - - case 'a': - { - char c = va_arg(va, int); - - el = PyUnicode_FromStringAndSize(&c, 1); - } - - 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': - { - /* Remove in v5.1. */ - - 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': - case 'L': - el = PyLong_FromLong(va_arg(va, int)); - 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 = PyBytes_FromString(s); - } - else - { - Py_INCREF(Py_None); - el = Py_None; - } - } - - break; - - case 'A': - { - char *s = va_arg(va, char *); - - if (s != NULL) - { - el = PyUnicode_FromString(s); - } - 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, (Py_ssize_t)wcslen(s)); - else - { - Py_INCREF(Py_None); - el = Py_None; - } - } -#else - raiseNoWChar(); - el = NULL; -#endif - - break; - - case 't': - case 'u': - case 'M': - el = PyLong_FromUnsignedLong(va_arg(va, unsigned)); - break; - - case '=': - el = PyLong_FromUnsignedLong(va_arg(va, size_t)); - break; - - case 'B': - { - /* Remove in v5.1. */ - - 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->wt_td, 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': - { - /* Remove in v5.1. */ - - 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->wt_td, 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 *); - Py_ssize_t l = va_arg(va, Py_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; - - case 'z': - { - const char *name = va_arg(va, const char *); - void *p = va_arg(va, void *); - - if (p == NULL) - { - el = Py_None; - Py_INCREF(el); - } - else - { - el = PyCapsule_New(p, name, NULL); - } - } - - 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. As of v9.0 of the API this - * is only ever called by handwritten code. - */ -static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res, - const char *fmt, ...) -{ - int rc; - va_list va; - - va_start(va, fmt); - rc = parseResult(method, res, NULL, fmt, va); - va_end(va); - - if (isErr != NULL && rc < 0) - *isErr = TRUE; - - return rc; -} - - -/* - * Parse a result object based on a format string. - */ -static int sip_api_parse_result_ex(sip_gilstate_t gil_state, - sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, - PyObject *method, PyObject *res, const char *fmt, ...) -{ - int rc; - - if (res != NULL) - { - va_list va; - - va_start(va, fmt); - rc = parseResult(method, res, deref_mixin(py_self), fmt, va); - va_end(va); - - Py_DECREF(res); - } - else - { - rc = -1; - } - - Py_DECREF(method); - - if (rc < 0) - sip_api_call_error_handler(error_handler, py_self, gil_state); - - SIP_RELEASE_GIL(gil_state); - - return rc; -} - - -/* - * Call a virtual error handler. This is called with the GIL and from the - * thread that raised the error. - */ -static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, - sipSimpleWrapper *py_self, sip_gilstate_t sipGILState) -{ - if (error_handler != NULL) - error_handler(deref_mixin(py_self), sipGILState); - else - PyErr_Print(); -} - - -/* - * Do the main work of parsing a result object based on a format string. - */ -static int parseResult(PyObject *method, PyObject *res, - sipSimpleWrapper *py_self, const char *fmt, va_list va) -{ - int tupsz, rc = 0; - - /* We rely on PyErr_Occurred(). */ - PyErr_Clear(); - - /* Get self if it is provided as an argument. */ - if (*fmt == 'S') - { - py_self = va_arg(va, sipSimpleWrapper *); - ++fmt; - } - - /* Basic validation of the format string. */ - if (*fmt == '(') - { - char ch; - const char *cp = ++fmt; - int sub_format = FALSE; - - tupsz = 0; - - while ((ch = *cp++) != ')') - { - if (ch == '\0') - { - PyErr_Format(PyExc_SystemError, "sipParseResult(): invalid format string \"%s\"", fmt - 1); - rc = -1; - - break; - } - - if (sub_format) - { - sub_format = FALSE; - } - else - { - ++tupsz; - - /* Some format characters have a sub-format. */ - if (strchr("aAHDC", ch) != NULL) - sub_format = TRUE; - } - } - - 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 **); - Py_ssize_t *szp = va_arg(va, Py_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 **); - Py_ssize_t *szp = va_arg(va, Py_ssize_t *); - - if (parseWCharArray(arg, p, szp) < 0) - invalid = TRUE; - } -#else - raiseNoWChar(); - invalid = TRUE; -#endif - - break; - - case 'b': - { - char *p = va_arg(va, void *); - int v = sip_api_convert_to_bool(arg); - - if (v < 0) - invalid = TRUE; - else if (p != NULL) - sipSetBool(p, 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 *p = va_arg(va, double *); - double v = PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'E': - { - /* Remove in v5.1. */ - - PyTypeObject *et = va_arg(va, PyTypeObject *); - int *p = va_arg(va, int *); - int v = sip_api_convert_to_enum(arg, ((sipEnumTypeObject *)et)->type); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'F': - { - sipTypeDef *td = va_arg(va, sipTypeDef *); - int *p = va_arg(va, int *); - int v = sip_api_convert_to_enum(arg, td); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'f': - { - float *p = va_arg(va, float *); - float v = (float)PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'L': - { - signed char *p = va_arg(va, signed char *); - signed char v = sip_api_long_as_signed_char(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'M': - { - unsigned char *p = va_arg(va, unsigned char *); - unsigned char v = sip_api_long_as_unsigned_char(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'h': - { - signed short *p = va_arg(va, signed short *); - signed short v = sip_api_long_as_short(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 't': - { - unsigned short *p = va_arg(va, unsigned short *); - unsigned short v = sip_api_long_as_unsigned_short(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'e': - { - int *p = va_arg(va, int *); - int v = long_as_nonoverflow_int(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'i': - { - int *p = va_arg(va, int *); - int v = sip_api_long_as_int(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'u': - { - unsigned *p = va_arg(va, unsigned *); - unsigned v = sip_api_long_as_unsigned_int(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case '=': - { - size_t *p = va_arg(va, size_t *); - size_t v = sip_api_long_as_size_t(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'l': - { - long *p = va_arg(va, long *); - long v = sip_api_long_as_long(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'm': - { - unsigned long *p = va_arg(va, unsigned long *); - unsigned long v = sip_api_long_as_unsigned_long(arg); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'n': - { -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG *p = va_arg(va, PY_LONG_LONG *); - PY_LONG_LONG v = sip_api_long_as_long_long(arg); -#else - long *p = va_arg(va, long *); - long v = sip_api_long_as_long(arg); -#endif - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'o': - { -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG *p = va_arg(va, unsigned PY_LONG_LONG *); - unsigned PY_LONG_LONG v = sip_api_long_as_unsigned_long_long(arg); -#else - unsigned long *p = va_arg(va, unsigned long *); - unsigned long v = sip_api_long_as_unsigned_long(arg); -#endif - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 's': - { - /* Remove in v5.1. */ - - 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 *)py_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 - sip_api_keep_reference((PyObject *)py_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': - { - /* Remove in v5.1. */ - - 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->wt_td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), state, &iserr); - - if (iserr) - invalid = TRUE; - } - } - - break; - - case 'D': - { - /* Remove in v5.1. */ - - 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); - - if (cpp != NULL) - assign_helper(cpp, 0, val); - - sip_api_release_type(val, td, state); - } - else if (cpp != NULL) - { - *(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)) - { - if (p != NULL) - { - Py_INCREF(arg); - *p = arg; - } - } - else - { - invalid = TRUE; - } - } - - break; - - case 'O': - { - PyObject **p = va_arg(va, PyObject **); - - if (p != NULL) - { - Py_INCREF(arg); - *p = arg; - } - } - - break; - - case 'T': - { - PyTypeObject *type = va_arg(va, PyTypeObject *); - PyObject **p = va_arg(va, PyObject **); - - if (PyObject_TypeCheck(arg, type)) - { - if (p != NULL) - { - Py_INCREF(arg); - *p = arg; - } - } - else - { - invalid = TRUE; - } - } - - break; - - case 'V': - { - void *v = sip_api_convert_to_void_ptr(arg); - void **p = va_arg(va, void **); - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - - break; - - case 'z': - { - const char *name = va_arg(va, const char *); - void **p = va_arg(va, void **); - - if (arg == Py_None) - { - if (p != NULL) - *p = NULL; - } - else - { -#if defined(SIP_USE_CAPSULE) - void *v = PyCapsule_GetPointer(arg, name); -#else - void *v = sip_api_convert_to_void_ptr(arg); - - (void)name; -#endif - - if (PyErr_Occurred()) - invalid = TRUE; - else if (p != NULL) - *p = v; - } - } - - break; - - case 'Z': - if (arg != Py_None) - invalid = TRUE; - - break; - - case '!': - { - PyObject **p = va_arg(va, PyObject **); - - if (PyObject_CheckBuffer(arg)) - { - if (p != NULL) - { - Py_INCREF(arg); - *p = arg; - } - } - else - { - invalid = TRUE; - } - } - - break; - - case '$': - { - PyObject **p = va_arg(va, PyObject **); - - if (arg == Py_None || PyObject_CheckBuffer(arg)) - { - if (p != NULL) - { - Py_INCREF(arg); - *p = arg; - } - } - else - { - 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; - } - } - } - - return rc; -} - - -/* - * 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; - - if (unused != NULL) - { - /* - * Initialise the return of any unused keyword arguments. This is - * used by any ctor overload. - */ - *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 - { - /* Indicate that an exception has been raised. */ - *parseErrp = Py_None; - Py_INCREF(Py_None); - } - } - - Py_DECREF(sipArgs); - - return ok; -} - - -/* - * Return a string as a Python object that describes an argument with an - * unexpected type. - */ -static PyObject *bad_type_str(int arg_nr, PyObject *arg) -{ - return PyUnicode_FromFormat("argument %d has unexpected type '%s'", arg_nr, - Py_TYPE(arg)->tp_name); -} - - -/* - * Adds a failure about an argument with an incorrect type to the current list - * of exceptions. - */ -static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg) -{ - PyObject *detail = bad_type_str(arg_nr + 1, arg); - - if (detail == NULL) - return sipErrorFail; - - PyErr_SetObject(PyExc_TypeError, detail); - Py_DECREF(detail); - - return sipErrorContinue; -} - - -/* - * Adds the current exception to the current list of exceptions (if it is a - * user exception) or replace the current list of exceptions. - */ -static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp) -{ - assert(*parseErrp == NULL); - - if (es == sipErrorContinue) - { - sipParseFailure failure; - PyObject *e_type, *e_traceback; - - /* Get the value of the exception. */ - PyErr_Fetch(&e_type, &failure.detail_obj, &e_traceback); - Py_XDECREF(e_type); - Py_XDECREF(e_traceback); - - failure.reason = Exception; - - add_failure(parseErrp, &failure); - - if (failure.reason == Raised) - { - Py_XDECREF(failure.detail_obj); - es = sipErrorFail; - } - } - - if (es == sipErrorFail) - { - Py_XDECREF(*parseErrp); - *parseErrp = Py_None; - Py_INCREF(Py_None); - } -} - - -/* - * The dtor for parse failure wrapped in a Python object. - */ -static void failure_dtor(PyObject *capsule) -{ - sipParseFailure *failure = (sipParseFailure *)PyCapsule_GetPointer(capsule, NULL); - - Py_XDECREF(failure->detail_obj); - - sip_api_free(failure); -} - - -/* - * Add a parse failure to the current list of exceptions. - */ -static void add_failure(PyObject **parseErrp, sipParseFailure *failure) -{ - sipParseFailure *failure_copy; - PyObject *failure_obj; - - /* Create the list if necessary. */ - if (*parseErrp == NULL && (*parseErrp = PyList_New(0)) == NULL) - { - failure->reason = Raised; - return; - } - - /* - * Make a copy of the failure, convert it to a Python object and add it to - * the list. We do it this way to make it as lightweight as possible. - */ - if ((failure_copy = sip_api_malloc(sizeof (sipParseFailure))) == NULL) - { - failure->reason = Raised; - return; - } - - *failure_copy = *failure; - - if ((failure_obj = PyCapsule_New(failure_copy, NULL, failure_dtor)) == NULL) - { - sip_api_free(failure_copy); - failure->reason = Raised; - return; - } - - /* Ownership of any detail object is now with the wrapped failure. */ - failure->detail_obj = NULL; - - if (PyList_Append(*parseErrp, failure_obj) < 0) - { - Py_DECREF(failure_obj); - failure->reason = Raised; - return; - } - - Py_DECREF(failure_obj); -} - - -/* - * Parse one or a pair of arguments to a C/C++ function without any side - * effects. - */ -static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0, - PyObject *sipArg1, const char *fmt, ...) -{ - int ok, selfarg; - sipSimpleWrapper *self; - PyObject *args; - va_list va; - - /* Previous second pass errors stop subsequent parses. */ - if (*parseErrp != NULL && !PyList_Check(*parseErrp)) - return FALSE; - - if ((args = PyTuple_New(sipArg1 != NULL ? 2 : 1)) == NULL) - { - /* Stop all parsing and indicate an exception has been raised. */ - Py_XDECREF(*parseErrp); - *parseErrp = Py_None; - Py_INCREF(Py_None); - - return FALSE; - } - - Py_INCREF(sipArg0); - PyTuple_SET_ITEM(args, 0, sipArg0); - - if (sipArg1 != NULL) - { - Py_INCREF(sipArg1); - PyTuple_SET_ITEM(args, 1, sipArg1); - } - - /* - * The first pass checks all the types and does conversions that are cheap - * and have no side effects. - */ - va_start(va, fmt); - ok = parsePass1(parseErrp, &self, &selfarg, args, NULL, NULL, NULL, fmt, - va); - va_end(va); - - if (ok) - { - /* - * The second pass does any remaining conversions now that we know we - * have the right signature. - */ - va_start(va, fmt); - ok = parsePass2(self, selfarg, args, NULL, NULL, fmt, va); - va_end(va); - - /* Remove any previous failed parses. */ - Py_XDECREF(*parseErrp); - - if (ok) - { - *parseErrp = NULL; - } - else - { - /* Indicate that an exception has been raised. */ - *parseErrp = Py_None; - Py_INCREF(Py_None); - } - } - - Py_DECREF(args); - - return ok; -} - - -/* - * First pass of the argument parse, converting those that can be done so - * without any side effects. Return TRUE if the arguments matched. - */ -static int parsePass1(PyObject **parseErrp, sipSimpleWrapper **selfp, - int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs, - const char **kwdlist, PyObject **unused, const char *fmt, va_list va) -{ - int compulsory, argnr, nr_args; - Py_ssize_t nr_pos_args, nr_kwd_args, nr_kwd_args_used; - sipParseFailure failure; - - failure.reason = Ok; - failure.detail_obj = NULL; - compulsory = TRUE; - argnr = 0; - nr_args = 0; - nr_pos_args = PyTuple_GET_SIZE(sipArgs); - nr_kwd_args = nr_kwd_args_used = 0; - - if (sipKwdArgs != NULL) - { - assert(PyDict_Check(sipKwdArgs)); - - nr_kwd_args = PyDict_Size(sipKwdArgs); - } - - /* - * Handle those format characters that deal with the "self" argument. They - * will always be the first one. - */ - *selfp = NULL; - *selfargp = FALSE; - - switch (*fmt++) - { - case 'B': - case 'p': - { - PyObject *self; - sipTypeDef *td; - - self = *va_arg(va, PyObject **); - td = va_arg(va, sipTypeDef *); - va_arg(va, void **); - - if (self == NULL) - { - if (!getSelfFromArgs(td, sipArgs, argnr, selfp)) - { - failure.reason = Unbound; - failure.detail_str = sipPyNameOfContainer( - &((sipClassTypeDef *)td)->ctd_container, td); - break; - } - - *selfargp = TRUE; - ++argnr; - } - else - *selfp = (sipSimpleWrapper *)self; - - break; - } - - case 'C': - *selfp = (sipSimpleWrapper *)va_arg(va,PyObject *); - break; - - default: - --fmt; - } - - /* - * Now handle the remaining arguments. We continue to parse if we get an - * overflow because that is, strictly speaking, a second pass error. - */ - while (failure.reason == Ok || failure.reason == Overflow) - { - char ch; - PyObject *arg; - - PyErr_Clear(); - - /* See if the following arguments are optional. */ - if ((ch = *fmt++) == '|') - { - compulsory = FALSE; - ch = *fmt++; - } - - /* See if we don't expect anything else. */ - - if (ch == '\0') - { - if (argnr < nr_pos_args) - { - /* There are still positional arguments. */ - failure.reason = TooMany; - } - else if (nr_kwd_args_used != nr_kwd_args) - { - /* - * Take a shortcut if no keyword arguments were used and we are - * interested in them. - */ - if (nr_kwd_args_used == 0 && unused != NULL) - { - Py_INCREF(sipKwdArgs); - *unused = sipKwdArgs; - } - else - { - PyObject *key, *value, *unused_dict = NULL; - Py_ssize_t pos = 0; - - /* - * Go through the keyword arguments to find any that were - * duplicates of positional arguments. For the remaining - * ones remember the unused ones if we are interested. - */ - while (PyDict_Next(sipKwdArgs, &pos, &key, &value)) - { - int a; - - if (!PyUnicode_Check(key)) - { - failure.reason = KeywordNotString; - failure.detail_obj = key; - Py_INCREF(key); - break; - } - - if (kwdlist != NULL) - { - /* Get the argument's index if it is one. */ - for (a = 0; a < nr_args; ++a) - { - const char *name = kwdlist[a]; - - if (name == NULL) - continue; - - if (PyUnicode_CompareWithASCIIString(key, name) == 0) - break; - } - } - else - { - a = nr_args; - } - - if (a == nr_args) - { - /* - * The name doesn't correspond to a keyword - * argument. - */ - if (unused == NULL) - { - /* - * It may correspond to a keyword argument of a - * different overload. - */ - failure.reason = UnknownKeyword; - failure.detail_obj = key; - Py_INCREF(key); - - break; - } - - /* - * Add it to the dictionary of unused arguments - * creating it if necessary. Note that if the - * unused arguments are actually used by a later - * overload then the parse will incorrectly - * succeed. This should be picked up (perhaps with - * a misleading exception) so long as the code that - * handles the unused arguments checks that it can - * handle them all. - */ - if (unused_dict == NULL && (*unused = unused_dict = PyDict_New()) == NULL) - { - failure.reason = Raised; - break; - } - - if (PyDict_SetItem(unused_dict, key, value) < 0) - { - failure.reason = Raised; - break; - } - } - else if (a < nr_pos_args - *selfargp) - { - /* - * The argument has been given positionally and as - * a keyword. - */ - failure.reason = Duplicate; - failure.detail_obj = key; - Py_INCREF(key); - break; - } - } - } - } - - break; - } - - /* Get the next argument. */ - arg = NULL; - failure.arg_nr = -1; - failure.arg_name = NULL; - - if (argnr < nr_pos_args) - { - arg = PyTuple_GET_ITEM(sipArgs, argnr); - failure.arg_nr = argnr + 1; - } - else if (nr_kwd_args != 0 && kwdlist != NULL) - { - const char *name = kwdlist[argnr - *selfargp]; - - if (name != NULL) - { - arg = PyDict_GetItemString(sipKwdArgs, name); - - if (arg != NULL) - ++nr_kwd_args_used; - - failure.arg_name = name; - } - } - - ++argnr; - ++nr_args; - - if (arg == NULL && compulsory) - { - if (ch == 'W') - { - /* - * A variable number of arguments was allowed but none were - * given. - */ - break; - } - - /* An argument was required. */ - failure.reason = TooFew; - - /* - * Check if there were any unused keyword arguments so that we give - * a (possibly) more accurate diagnostic in the case that a keyword - * argument has been mis-spelled. - */ - if (unused == NULL && sipKwdArgs != NULL && nr_kwd_args_used != nr_kwd_args) - { - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(sipKwdArgs, &pos, &key, &value)) - { - int a; - - if (!PyUnicode_Check(key)) - { - failure.reason = KeywordNotString; - failure.detail_obj = key; - Py_INCREF(key); - break; - } - - if (kwdlist != NULL) - { - /* Get the argument's index if it is one. */ - for (a = 0; a < nr_args; ++a) - { - const char *name = kwdlist[a]; - - if (name == NULL) - continue; - - if (PyUnicode_CompareWithASCIIString(key, name) == 0) - break; - } - } - else - { - a = nr_args; - } - - if (a == nr_args) - { - failure.reason = UnknownKeyword; - failure.detail_obj = key; - Py_INCREF(key); - - break; - } - } - } - - break; - } - - /* - * Handle the format character even if we don't have an argument so - * that we skip the right number of arguments. - */ - switch (ch) - { - case 'W': - /* Ellipsis. */ - break; - - case '@': - { - /* Implement /GetWrapper/. */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - *p = arg; - - /* Process the same argument next time round. */ - --argnr; - --nr_args; - - break; - } - - case 's': - { - /* String from a Python bytes or None. */ - - const char **p = va_arg(va, const char **); - - if (arg != NULL && parseBytes_AsString(arg, p) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'A': - { - /* String from a Python string or None. */ - - va_arg(va, PyObject **); - va_arg(va, const char **); - fmt++; - - if (arg != NULL && check_encoded_string(arg) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'a': - { - /* Character from a Python string. */ - - va_arg(va, char *); - fmt++; - - if (arg != NULL && check_encoded_string(arg) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'x': -#if defined(HAVE_WCHAR_H) - { - /* Wide string or None. */ - - wchar_t **p = va_arg(va, wchar_t **); - - if (arg != NULL && parseWCharString(arg, p) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } -#else - raiseNoWChar(); - failure.reason = Raised; - break; -#endif - - case 'U': - { - /* Slot name or callable, return the name or callable. */ - - char **sname = va_arg(va, char **); - PyObject **scall = va_arg(va, PyObject **); - - if (arg != NULL) - { - *sname = NULL; - *scall = NULL; - - if (PyBytes_Check(arg)) - { - char *s = PyBytes_AS_STRING(arg); - - if (*s == '1' || *s == '2' || *s == '9') - { - *sname = s; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - else if (PyCallable_Check(arg)) - { - *scall = arg; - } - else if (arg != Py_None) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'S': - { - /* Slot name, return the name. */ - - char **p = va_arg(va, char **); - - if (arg != NULL) - { - if (PyBytes_Check(arg)) - { - char *s = PyBytes_AS_STRING(arg); - - if (*s == '1' || *s == '2' || *s == '9') - { - *p = s; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'G': - { - /* Signal name, return the name. */ - - char **p = va_arg(va, char **); - - if (arg != NULL) - { - if (PyBytes_Check(arg)) - { - char *s = PyBytes_AS_STRING(arg); - - if (*s == '2' || *s == '9') - { - *p = s; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'r': - { - /* Sequence of class or mapped type instances. */ - - const sipTypeDef *td; - - td = va_arg(va, const sipTypeDef *); - va_arg(va, void **); - va_arg(va, Py_ssize_t *); - - if (arg != NULL && !canConvertFromSequence(arg, td)) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'J': - { - /* Class or mapped type instance. */ - - char sub_fmt = *fmt++; - const sipTypeDef *td; - int flags = sub_fmt - '0'; - int iflgs = 0; - - td = va_arg(va, const sipTypeDef *); - va_arg(va, void **); - - if (flags & FMT_AP_DEREF) - iflgs |= SIP_NOT_NONE; - - if (flags & FMT_AP_TRANSFER_THIS) - va_arg(va, PyObject **); - - if (flags & FMT_AP_NO_CONVERTORS) - iflgs |= SIP_NO_CONVERTORS; - else - va_arg(va, int *); - - if (arg != NULL && !sip_api_can_convert_to_type(arg, td, iflgs)) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'N': - { - /* Python object of given type or None. */ - - PyTypeObject *type = va_arg(va,PyTypeObject *); - PyObject **p = va_arg(va,PyObject **); - - if (arg != NULL) - { - if (arg == Py_None || PyObject_TypeCheck(arg,type)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'P': - { - /* Python object of any type with a sub-format. */ - - va_arg(va, PyObject **); - - /* Skip the sub-format. */ - ++fmt; - - break; - } - - case 'T': - { - /* Python object of given type. */ - - PyTypeObject *type = va_arg(va, PyTypeObject *); - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (PyObject_TypeCheck(arg,type)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'R': - { - /* Sub-class of QObject. */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (isQObject(arg)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'F': - { - /* Python callable object. */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (PyCallable_Check(arg)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'H': - { - /* Python callable object or None. */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (arg == Py_None || PyCallable_Check(arg)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case '!': - { - /* Python object that implements the buffer protocol. */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (PyObject_CheckBuffer(arg)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case '$': - { - /* - * Python object that implements the buffer protocol or None. - */ - - PyObject **p = va_arg(va, PyObject **); - - if (arg != NULL) - { - if (arg == Py_None || PyObject_CheckBuffer(arg)) - { - *p = arg; - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - } - - break; - } - - case 'q': - { - /* Qt receiver to connect. */ - - va_arg(va, char *); - va_arg(va, void **); - va_arg(va, const char **); - - if (arg != NULL && !isQObject(arg)) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'Q': - { - /* Qt receiver to disconnect. */ - - va_arg(va, char *); - va_arg(va, void **); - va_arg(va, const char **); - - if (arg != NULL && !isQObject(arg)) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'g': - case 'y': - { - /* Python slot to connect. */ - - va_arg(va, char *); - va_arg(va, void **); - va_arg(va, const char **); - - if (arg != NULL && (sipQtSupport == NULL || !PyCallable_Check(arg))) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'Y': - { - /* Python slot to disconnect. */ - - va_arg(va, char *); - va_arg(va, void **); - va_arg(va, const char **); - - if (arg != NULL && (sipQtSupport == NULL || !PyCallable_Check(arg))) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'k': - { - /* Char array or None. */ - - const char **p = va_arg(va, const char **); - Py_ssize_t *szp = va_arg(va, Py_ssize_t *); - - if (arg != NULL && parseBytes_AsCharArray(arg, p, szp) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'K': -#if defined(HAVE_WCHAR_H) - { - /* Wide char array or None. */ - - wchar_t **p = va_arg(va, wchar_t **); - Py_ssize_t *szp = va_arg(va, Py_ssize_t *); - - if (arg != NULL && parseWCharArray(arg, p, szp) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } -#else - raiseNoWChar(); - failure.reason = Raised; - break -#endif - - case 'c': - { - /* Character from a Python bytes. */ - - char *p = va_arg(va, char *); - - if (arg != NULL && parseBytes_AsChar(arg, p) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'w': -#if defined(HAVE_WCHAR_H) - { - /* Wide character. */ - - wchar_t *p = va_arg(va, wchar_t *); - - if (arg != NULL && parseWChar(arg, p) < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } -#else - raiseNoWChar(); - failure.reason = Raised; - break -#endif - - case 'b': - { - /* Bool. */ - - void *p = va_arg(va, void *); - - if (arg != NULL) - { - int v = sip_api_convert_to_bool(arg); - - if (v < 0) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - else - { - sipSetBool(p, v); - } - } - - break; - } - - case 'E': - { - /* Named enum or integer. */ - - sipTypeDef *td = va_arg(va, sipTypeDef *); - int *p = va_arg(va, int *); - - if (arg != NULL) - { - int v = sip_api_convert_to_enum(arg, td); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - } - - break; - - case 'e': - { - /* Anonymous enum. */ - - int *p = va_arg(va, int *); - - if (arg != NULL) - { - int v = long_as_nonoverflow_int(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - } - - break; - - case 'i': - { - /* Integer. */ - - int *p = va_arg(va, int *); - - if (arg != NULL) - { - int v = sip_api_long_as_int(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'u': - { - /* Unsigned integer. */ - - unsigned *p = va_arg(va, unsigned *); - - if (arg != NULL) - { - unsigned v = sip_api_long_as_unsigned_int(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case '=': - { - /* size_t integer. */ - - size_t *p = va_arg(va, size_t *); - - if (arg != NULL) - { - size_t v = sip_api_long_as_size_t(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'L': - { - /* Signed char. */ - - signed char *p = va_arg(va, signed char *); - - if (arg != NULL) - { - signed char v = sip_api_long_as_signed_char(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'M': - { - /* Unsigned char. */ - - unsigned char *p = va_arg(va, unsigned char *); - - if (arg != NULL) - { - unsigned char v = sip_api_long_as_unsigned_char(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'h': - { - /* Short integer. */ - - signed short *p = va_arg(va, signed short *); - - if (arg != NULL) - { - signed short v = sip_api_long_as_short(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 't': - { - /* Unsigned short integer. */ - - unsigned short *p = va_arg(va, unsigned short *); - - if (arg != NULL) - { - unsigned short v = sip_api_long_as_unsigned_short(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'l': - { - /* Long integer. */ - - long *p = va_arg(va, long *); - - if (arg != NULL) - { - long v = sip_api_long_as_long(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'm': - { - /* Unsigned long integer. */ - - unsigned long *p = va_arg(va, unsigned long *); - - if (arg != NULL) - { - unsigned long v = sip_api_long_as_unsigned_long(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'n': - { - /* Long long integer. */ - -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG *p = va_arg(va, PY_LONG_LONG *); -#else - long *p = va_arg(va, long *); -#endif - - if (arg != NULL) - { -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG v = sip_api_long_as_long_long(arg); -#else - long v = sip_api_long_as_long(arg); -#endif - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'o': - { - /* Unsigned long long integer. */ - -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG *p = va_arg(va, unsigned PY_LONG_LONG *); -#else - unsigned long *p = va_arg(va, unsigned long *); -#endif - - if (arg != NULL) - { -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG v = sip_api_long_as_unsigned_long_long(arg); -#else - unsigned long v = sip_api_long_as_unsigned_long(arg); -#endif - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - else - *p = v; - } - - break; - } - - case 'f': - { - /* Float. */ - - float *p = va_arg(va, float *); - - if (arg != NULL) - { - double v = PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - else - { - *p = (float)v; - } - } - - break; - } - - case 'X': - { - /* Constrained types. */ - - char sub_fmt = *fmt++; - - if (sub_fmt == 'E') - { - /* Named enum. */ - - sipTypeDef *td = va_arg(va, sipTypeDef *); - int *p = va_arg(va, int *); - - if (arg != NULL) - { - *p = convert_to_enum(arg, td, FALSE); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, arg); - } - } - else - { - void *p = va_arg(va, void *); - - if (arg != NULL) - { - switch (sub_fmt) - { - case 'b': - { - /* Boolean. */ - - if (PyBool_Check(arg)) - { - sipSetBool(p, (arg == Py_True)); - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'd': - { - /* Double float. */ - - if (PyFloat_Check(arg)) - { - *(double *)p = PyFloat_AS_DOUBLE(arg); - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'f': - { - /* Float. */ - - if (PyFloat_Check(arg)) - { - *(float *)p = (float)PyFloat_AS_DOUBLE(arg); - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - - case 'i': - { - /* Integer. */ - - if (PyLong_Check(arg)) - { - *(int *)p = sip_api_long_as_int(arg); - - if (PyErr_Occurred()) - handle_failed_int_conversion(&failure, - arg); - } - else - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - - break; - } - } - } - } - - break; - } - - case 'd': - { - /* Double float. */ - - double *p = va_arg(va,double *); - - if (arg != NULL) - { - double v = PyFloat_AsDouble(arg); - - if (PyErr_Occurred()) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - else - { - *p = v; - } - } - - break; - } - - case 'v': - { - /* Void pointer. */ - - void **p = va_arg(va, void **); - - if (arg != NULL) - { - void *v = sip_api_convert_to_void_ptr(arg); - - if (PyErr_Occurred()) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - else - { - *p = v; - } - } - - break; - } - - case 'z': - { - /* Void pointer as a capsule. */ - - const char *name = va_arg(va, const char *); - void **p = va_arg(va, void **); - - if (arg == Py_None) - { - *p = NULL; - } - else if (arg != NULL) - { - void *v = PyCapsule_GetPointer(arg, name); - - if (PyErr_Occurred()) - { - failure.reason = WrongType; - failure.detail_obj = arg; - Py_INCREF(arg); - } - else - { - *p = v; - } - } - - break; - } - } - - if ((failure.reason == Ok || failure.reason == Overflow) && ch == 'W') - { - /* An ellipsis matches everything and ends the parse. */ - break; - } - } - - /* Handle parse failures appropriately. */ - - if (failure.reason == Ok) - return TRUE; - - if (failure.reason == Overflow) - { - /* - * We have successfully parsed the signature but one of the arguments - * has been found to overflow. Raise an appropriate exception and - * ensure we don't parse any subsequent overloads. - */ - if (failure.overflow_arg_nr >= 0) - { - PyErr_Format(PyExc_OverflowError, "argument %d overflowed: %S", - failure.overflow_arg_nr, failure.detail_obj); - } - else - { - PyErr_Format(PyExc_OverflowError, "argument '%s' overflowed: %S", - failure.overflow_arg_name, failure.detail_obj); - } - - /* The overflow exception has now been raised. */ - failure.reason = Raised; - } - - if (failure.reason != Raised) - add_failure(parseErrp, &failure); - - if (failure.reason == Raised) - { - Py_XDECREF(failure.detail_obj); - - /* - * Discard any previous errors and flag that the exception we want the - * user to see has been raised. - */ - Py_XDECREF(*parseErrp); - *parseErrp = Py_None; - Py_INCREF(Py_None); - } - - return FALSE; -} - - -/* - * Called after a failed conversion of an integer. - */ -static void handle_failed_int_conversion(sipParseFailure *pf, PyObject *arg) -{ - PyObject *xtype, *xvalue, *xtb; - - assert(pf->reason == Ok || pf->reason == Overflow); - - PyErr_Fetch(&xtype, &xvalue, &xtb); - - if (PyErr_GivenExceptionMatches(xtype, PyExc_OverflowError) && xvalue != NULL) - { - /* Remove any previous overflow exception. */ - Py_XDECREF(pf->detail_obj); - - pf->reason = Overflow; - pf->overflow_arg_nr = pf->arg_nr; - pf->overflow_arg_name = pf->arg_name; - pf->detail_obj = xvalue; - Py_INCREF(xvalue); - } - else - { - pf->reason = WrongType; - pf->detail_obj = arg; - Py_INCREF(arg); - } - - PyErr_Restore(xtype, xvalue, xtb); -} - - -/* - * Second pass of the argument parse, converting the remaining ones that might - * have side effects. Return TRUE if there was no error. - */ -static int parsePass2(sipSimpleWrapper *self, int selfarg, PyObject *sipArgs, - PyObject *sipKwdArgs, const char **kwdlist, const char *fmt, - va_list va) -{ - int a, ok; - Py_ssize_t nr_pos_args; - - /* Handle the conversions of "self" first. */ - switch (*fmt++) - { - case 'B': - { - /* - * The address of a C++ instance when calling one of its public - * methods. - */ - - const sipTypeDef *td; - void **p; - - *va_arg(va, PyObject **) = (PyObject *)self; - td = va_arg(va, const sipTypeDef *); - p = va_arg(va, void **); - - if ((*p = sip_api_get_cpp_ptr(self, td)) == NULL) - return FALSE; - - break; - } - - case 'p': - { - /* - * The address of a C++ instance when calling one of its protected - * methods. - */ - - const sipTypeDef *td; - void **p; - - *va_arg(va, PyObject **) = (PyObject *)self; - td = va_arg(va, const sipTypeDef *); - p = va_arg(va, void **); - - if ((*p = getComplexCppPtr(self, td)) == NULL) - return FALSE; - - break; - } - - case 'C': - va_arg(va, PyObject *); - break; - - default: - --fmt; - } - - ok = TRUE; - nr_pos_args = PyTuple_GET_SIZE(sipArgs); - - for (a = (selfarg ? 1 : 0); *fmt != '\0' && *fmt != 'W' && ok; ++a) - { - char ch; - PyObject *arg; - - /* Skip the optional character. */ - if ((ch = *fmt++) == '|') - ch = *fmt++; - - /* Get the next argument. */ - arg = NULL; - - if (a < nr_pos_args) - { - arg = PyTuple_GET_ITEM(sipArgs, a); - } - else if (sipKwdArgs != NULL) - { - const char *name = kwdlist[a - selfarg]; - - if (name != NULL) - arg = PyDict_GetItemString(sipKwdArgs, name); - } - - /* - * Do the outstanding conversions. For most types it has already been - * done, so we are just skipping the parameters. - */ - switch (ch) - { - case '@': - /* Implement /GetWrapper/. */ - va_arg(va, PyObject **); - - /* Process the same argument next time round. */ - --a; - - break; - - case 'q': - { - /* Qt receiver to connect. */ - - char *sig = va_arg(va, char *); - void **rx = va_arg(va, void **); - const char **slot = va_arg(va, const char **); - - if (arg != NULL) - { - *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg, - *slot, slot, 0); - - if (*rx == NULL) - return FALSE; - } - - break; - } - - case 'Q': - { - /* Qt receiver to disconnect. */ - - char *sig = va_arg(va, char *); - void **rx = va_arg(va, void **); - const char **slot = va_arg(va, const char **); - - if (arg != NULL) - *rx = sipGetRx(self, sig, arg, *slot, slot); - - break; - } - - case 'g': - { - /* Python single shot slot to connect. */ - - char *sig = va_arg(va, char *); - void **rx = va_arg(va, void **); - const char **slot = va_arg(va, const char **); - - if (arg != NULL) - { - *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg, - NULL, slot, SIP_SINGLE_SHOT); - - if (*rx == NULL) - return FALSE; - } - - break; - } - - case 'y': - { - /* Python slot to connect. */ - - char *sig = va_arg(va, char *); - void **rx = va_arg(va, void **); - const char **slot = va_arg(va, const char **); - - if (arg != NULL) - { - *rx = sip_api_convert_rx((sipWrapper *)self, sig, arg, - NULL, slot, 0); - - if (*rx == NULL) - return FALSE; - } - - break; - } - - case 'Y': - { - /* Python slot to disconnect. */ - - char *sig = va_arg(va, char *); - void **rx = va_arg(va, void **); - const char **slot = va_arg(va, const char **); - - if (arg != NULL) - *rx = sipGetRx(self, sig, arg, NULL, slot); - - break; - } - - case 'r': - { - /* Sequence of class or mapped type instances. */ - - const sipTypeDef *td; - void **array; - Py_ssize_t *nr_elem; - - td = va_arg(va, const sipTypeDef *); - array = va_arg(va, void **); - nr_elem = va_arg(va, Py_ssize_t *); - - if (arg != NULL && !convertFromSequence(arg, td, array, nr_elem)) - return FALSE; - - break; - } - - case 'J': - { - /* Class or mapped type instance. */ - - int flags = *fmt++ - '0'; - const sipTypeDef *td; - void **p; - int iflgs = 0; - int *state; - PyObject *xfer, **owner; - - td = va_arg(va, const sipTypeDef *); - p = va_arg(va, void **); - - if (flags & FMT_AP_TRANSFER) - xfer = (self ? (PyObject *)self : arg); - else if (flags & FMT_AP_TRANSFER_BACK) - xfer = Py_None; - else - xfer = NULL; - - if (flags & FMT_AP_DEREF) - iflgs |= SIP_NOT_NONE; - - if (flags & FMT_AP_TRANSFER_THIS) - owner = va_arg(va, PyObject **); - - if (flags & FMT_AP_NO_CONVERTORS) - { - iflgs |= SIP_NO_CONVERTORS; - state = NULL; - } - else - { - state = va_arg(va, int *); - } - - if (arg != NULL) - { - int iserr = FALSE; - - *p = sip_api_convert_to_type(arg, td, xfer, iflgs, state, - &iserr); - - if (iserr) - return FALSE; - - if (flags & FMT_AP_TRANSFER_THIS && *p != NULL) - *owner = arg; - } - - break; - } - - case 'P': - { - /* Python object of any type with a sub-format. */ - - PyObject **p = va_arg(va, PyObject **); - int flags = *fmt++ - '0'; - - if (arg != NULL) - { - if (flags & FMT_AP_TRANSFER) - { - Py_XINCREF(arg); - } - else if (flags & FMT_AP_TRANSFER_BACK) - { - Py_XDECREF(arg); - } - - *p = arg; - } - - break; - } - - case 'X': - { - /* Constrained types. */ - - if (*fmt++ == 'E') - va_arg(va, void *); - - va_arg(va, void *); - - break; - } - - case 'A': - { - /* String from a Python string or None. */ - - PyObject **keep = va_arg(va, PyObject **); - const char **p = va_arg(va, const char **); - char sub_fmt = *fmt++; - - if (arg != NULL) - { - PyObject *s = NULL; - - switch (sub_fmt) - { - case 'A': - s = parseString_AsASCIIString(arg, p); - break; - - case 'L': - s = parseString_AsLatin1String(arg, p); - break; - - case '8': - s = parseString_AsUTF8String(arg, p); - break; - } - - if (s == NULL) - return FALSE; - - *keep = s; - } - - break; - } - - case 'a': - { - /* Character from a Python string. */ - - char *p = va_arg(va, char *); - char sub_fmt = *fmt++; - - if (arg != NULL) - { - int enc; - - switch (sub_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; - } - - if (enc < 0) - return FALSE; - } - - break; - } - - /* - * Every other argument is a pointer and only differ in how many there - * are. - */ - case 'N': - case 'T': - case 'k': - case 'K': - case 'U': - case 'E': - va_arg(va, void *); - - /* Drop through. */ - - default: - va_arg(va, void *); - } - } - - /* Handle any ellipsis argument. */ - if (*fmt == 'W') - { - PyObject *al; - int da = 0; - - /* Create a tuple for any remaining arguments. */ - if ((al = PyTuple_New(nr_pos_args - a)) == NULL) - return FALSE; - - while (a < nr_pos_args) - { - PyObject *arg = PyTuple_GET_ITEM(sipArgs, a); - - /* Add the remaining argument to the tuple. */ - Py_INCREF(arg); - PyTuple_SET_ITEM(al, da, arg); - - ++a; - ++da; - } - - /* Return the tuple. */ - *va_arg(va, PyObject **) = al; - } - - return TRUE; -} - - -/* - * Return TRUE if an object is a QObject. - */ -static int isQObject(PyObject *obj) -{ - return (sipQtSupport != NULL && PyObject_TypeCheck(obj, sipTypeAsPyTypeObject(sipQObjectType))); -} - - -/* - * See if a Python object is a sequence of a particular type. - */ -static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td) -{ - Py_ssize_t i, size = PySequence_Size(seq); - - if (size < 0) - return FALSE; - - for (i = 0; i < size; ++i) - { - int ok; - PyObject *val_obj; - - if ((val_obj = PySequence_GetItem(seq, i)) == NULL) - return FALSE; - - ok = sip_api_can_convert_to_type(val_obj, td, - SIP_NO_CONVERTORS|SIP_NOT_NONE); - - Py_DECREF(val_obj); - - if (!ok) - return FALSE; - } - - return TRUE; -} - - -/* - * Convert a Python sequence to an array that has already "passed" - * canConvertFromSequence(). Return TRUE if the conversion was successful. - */ -static int convertFromSequence(PyObject *seq, const sipTypeDef *td, - void **array, Py_ssize_t *nr_elem) -{ - int iserr = 0; - Py_ssize_t i, size = PySequence_Size(seq); - sipArrayFunc array_helper; - sipAssignFunc assign_helper; - void *array_mem; - - /* Get the type's helpers. */ - if (sipTypeIsMapped(td)) - { - array_helper = ((const sipMappedTypeDef *)td)->mtd_array; - assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign; - } - else - { - array_helper = ((const sipClassTypeDef *)td)->ctd_array; - assign_helper = ((const sipClassTypeDef *)td)->ctd_assign; - } - - assert(array_helper != NULL); - assert(assign_helper != NULL); - - /* - * Create the memory for the array of values. Note that this will leak if - * there is an error. - */ - array_mem = array_helper(size); - - for (i = 0; i < size; ++i) - { - PyObject *val_obj; - void *val; - - if ((val_obj = PySequence_GetItem(seq, i)) == NULL) - return FALSE; - - val = sip_api_convert_to_type(val_obj, td, NULL, - SIP_NO_CONVERTORS|SIP_NOT_NONE, NULL, &iserr); - - Py_DECREF(val_obj); - - if (iserr) - return FALSE; - - assign_helper(array_mem, i, val); - } - - *array = array_mem; - *nr_elem = size; - - return TRUE; -} - - -/* - * Convert an array of a type to a Python sequence. - */ -static PyObject *convertToSequence(void *array, Py_ssize_t nr_elem, - const sipTypeDef *td) -{ - Py_ssize_t i; - PyObject *seq; - sipCopyFunc copy_helper; - - /* Get the type's copy helper. */ - if (sipTypeIsMapped(td)) - copy_helper = ((const sipMappedTypeDef *)td)->mtd_copy; - else - copy_helper = ((const sipClassTypeDef *)td)->ctd_copy; - - assert(copy_helper != NULL); - - if ((seq = PyTuple_New(nr_elem)) == NULL) - return NULL; - - for (i = 0; i < nr_elem; ++i) - { - void *el = copy_helper(array, i); - PyObject *el_obj = sip_api_convert_from_new_type(el, td, NULL); - - if (el_obj == NULL) - { - release(el, td, 0); - Py_DECREF(seq); - } - - PyTuple_SET_ITEM(seq, i, el_obj); - } - - return seq; -} - - -/* - * Perform housekeeping after a C++ instance has been destroyed. - */ -void sip_api_instance_destroyed(sipSimpleWrapper *sw) -{ - sip_api_instance_destroyed_ex(&sw); -} - - -/* - * Carry out actions common to all dtors. - */ -static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp) -{ - /* If there is no interpreter just to the minimum and get out. */ - if (sipInterpreter == NULL) - { - *sipSelfp = NULL; - return; - } - - SIP_BLOCK_THREADS - - sipSimpleWrapper *sipSelf = *sipSelfp; - - if (sipSelf != NULL) - { - PyObject *xtype, *xvalue, *xtb; - - /* We may be tidying up after an exception so preserve it. */ - PyErr_Fetch(&xtype, &xvalue, &xtb); - callPyDtor(sipSelf); - PyErr_Restore(xtype, xvalue, xtb); - - sipOMRemoveObject(&cppPyMap, sipSelf); - - /* - * This no longer points to anything useful. Actually it might do as - * the partially destroyed C++ instance may still be trying to invoke - * reimplemented virtuals. - */ - clear_access_func(sipSelf); - - /* - * If C/C++ has a reference (and therefore no parent) then remove it. - * Otherwise remove the object from any parent. - */ - if (sipCppHasRef(sipSelf)) - { - sipResetCppHasRef(sipSelf); - Py_DECREF(sipSelf); - } - else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)&sipWrapper_Type)) - { - removeFromParent((sipWrapper *)sipSelf); - } - - /* - * Normally this is done in the generated dealloc function. However - * this is only called if the pointer/access function has not been - * reset (which it has). It acts as a guard to prevent any further - * invocations of reimplemented virtuals. - */ - *sipSelfp = NULL; - } - - SIP_UNBLOCK_THREADS -} - - -/* - * Clear any access function so that sip_api_get_address() will always return a - * NULL pointer. - */ -static void clear_access_func(sipSimpleWrapper *sw) -{ - if (sw->access_func != NULL) - { - sw->access_func(sw, ReleaseGuard); - sw->access_func = NULL; - } - - sw->data = NULL; -} - - -/* - * Call self.__dtor__() if it is implemented. - */ -static void callPyDtor(sipSimpleWrapper *self) -{ - sip_gilstate_t sipGILState; - char pymc = 0; - PyObject *meth; - - meth = sip_api_is_py_method_12_8(&sipGILState, &pymc, &self, NULL, - "__dtor__"); - - if (meth != NULL) - { - PyObject *res = sip_api_call_method(0, meth, "", NULL); - - Py_DECREF(meth); - - /* Discard any result. */ - Py_XDECREF(res); - - /* Handle any error the best we can. */ - if (PyErr_Occurred()) - PyErr_Print(); - - SIP_RELEASE_GIL(sipGILState); - } -} - - -/* - * Add a wrapper to it's parent owner. The wrapper must not currently have a - * parent and, therefore, no siblings. - */ -static void addToParent(sipWrapper *self, sipWrapper *owner) -{ - if (owner->first_child != NULL) - { - self->sibling_next = owner->first_child; - owner->first_child->sibling_prev = self; - } - - owner->first_child = self; - self->parent = owner; - - /* - * The owner holds a real reference so that the cyclic garbage collector - * works properly. - */ - Py_INCREF((sipSimpleWrapper *)self); -} - - -/* - * Remove a wrapper from it's parent if it has one. - */ -static void removeFromParent(sipWrapper *self) -{ - if (self->parent != NULL) - { - if (self->parent->first_child == self) - self->parent->first_child = self->sibling_next; - - if (self->sibling_next != NULL) - self->sibling_next->sibling_prev = self->sibling_prev; - - if (self->sibling_prev != NULL) - self->sibling_prev->sibling_next = self->sibling_next; - - self->parent = NULL; - self->sibling_next = NULL; - self->sibling_prev = NULL; - - /* - * We must do this last, after all the pointers are correct, because - * this is used by the clear slot. - */ - Py_DECREF((sipSimpleWrapper *)self); - } -} - - -/* - * Detach and children of a parent. - */ -static void detachChildren(sipWrapper *self) -{ - while (self->first_child != NULL) - removeFromParent(self->first_child); -} - - -/* - * Convert a sequence index. Return the index or a negative value if there was - * an error. - */ -static Py_ssize_t sip_api_convert_from_sequence_index(Py_ssize_t idx, - Py_ssize_t len) -{ - /* Negative indices start from the other end. */ - if (idx < 0) - idx = len + idx; - - if (idx < 0 || idx >= len) - { - PyErr_Format(PyExc_IndexError, "sequence index out of range"); - return -1; - } - - return idx; -} - - -/* - * Return a tuple of the base class of a type that has no explicit super-type. - */ -static PyObject *getDefaultBase(void) -{ - static PyObject *default_base = NULL; - - /* Only do this once. */ - if (default_base == NULL) - { - if ((default_base = PyTuple_Pack(1, (PyObject *)&sipWrapper_Type)) == NULL) - return NULL; - } - - Py_INCREF(default_base); - - return default_base; -} - - -/* - * Return a tuple of the base class of a simple type that has no explicit - * super-type. - */ -static PyObject *getDefaultSimpleBase(void) -{ - static PyObject *default_simple_base = NULL; - - /* Only do this once. */ - if (default_simple_base == NULL) - { - if ((default_simple_base = PyTuple_Pack(1, (PyObject *)&sipSimpleWrapper_Type)) == NULL) - return NULL; - } - - Py_INCREF(default_simple_base); - - return default_simple_base; -} - - -/* - * Return the dictionary of a type. - */ -static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict, - sipExportedModuleDef *client) -{ - /* - * Initialise the scoping type if necessary. It will always be in the - * same module if it needs doing. - */ - if (sipTypeIsMapped(td)) - { - if (createMappedType(client, (sipMappedTypeDef *)td, mod_dict) < 0) - return NULL; - - /* Check that the mapped type can act as a container. */ - assert(sipTypeAsPyTypeObject(td) != NULL); - } - else - { - if (createClassType(client, (sipClassTypeDef *)td, mod_dict) < 0) - return NULL; - } - - return (sipTypeAsPyTypeObject(td))->tp_dict; -} - - -/* - * Create a container type and return a borrowed reference to it. - */ -static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td, - PyObject *bases, PyObject *metatype, PyObject *mod_dict, - PyObject *type_dict, sipExportedModuleDef *client) -{ - PyObject *py_type, *scope_dict, *name, *args; - sipTypeDef *scope_td; - - /* Get the dictionary to place the type in. */ - if (cod->cod_scope.sc_flag) - { - scope_td = NULL; - scope_dict = mod_dict; - } - else - { - scope_td = getGeneratedType(&cod->cod_scope, client); - scope_dict = getScopeDict(scope_td, mod_dict, client); - - if (scope_dict == NULL) - goto reterr; - } - - /* Create an object corresponding to the type name. */ - if ((name = PyUnicode_FromString(sipPyNameOfContainer(cod, td))) == NULL) - goto reterr; - - /* Create the type by calling the metatype. */ - if ((args = PyTuple_Pack(3, name, bases, type_dict)) == NULL) - goto relname; - - /* Pass the type via the back door. */ - assert(currentType == NULL); - currentType = td; - py_type = PyObject_Call(metatype, args, NULL); - currentType = NULL; - - if (py_type == NULL) - goto relargs; - - /* Fix __qualname__ if there is a scope. */ - if (scope_td != NULL) - { - PyHeapTypeObject *ht; - PyObject *qualname = get_qualname(scope_td, name); - - if (qualname == NULL) - goto reltype; - - ht = (PyHeapTypeObject *)py_type; - - Py_CLEAR(ht->ht_qualname); - ht->ht_qualname = qualname; - } - - /* Add the type to the "parent" dictionary. */ - if (PyDict_SetItem(scope_dict, name, py_type) < 0) - goto reltype; - - Py_DECREF(args); - Py_DECREF(name); - - return py_type; - - /* Unwind on error. */ - -reltype: - Py_DECREF(py_type); - -relargs: - Py_DECREF(args); - -relname: - Py_DECREF(name); - -reterr: - return NULL; -} - - -/* - * Create a single class type object. - */ -static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd, - PyObject *mod_dict) -{ - PyObject *bases, *metatype, *py_type, *type_dict; - sipEncodedTypeDef *sup; - int i; - - /* Handle the trivial case where we have already been initialised. */ - if (ctd->ctd_base.td_module != NULL) - return 0; - - /* Set this up now to gain access to the string pool. */ - ctd->ctd_base.td_module = client; - - /* Create the tuple of super-types. */ - if ((sup = ctd->ctd_supers) == NULL) - { - if (ctd->ctd_supertype < 0) - { - bases = (sipTypeIsNamespace(&ctd->ctd_base) ? getDefaultSimpleBase() : getDefaultBase()); - } - else - { - PyObject *supertype; - const char *supertype_name = sipNameFromPool(client, - ctd->ctd_supertype); - - if ((supertype = findPyType(supertype_name)) == NULL) - goto reterr; - - bases = PyTuple_Pack(1, supertype); - } - - if (bases == NULL) - goto reterr; - } - else - { - int nrsupers = 0; - - do - ++nrsupers; - while (!sup++->sc_flag); - - if ((bases = PyTuple_New(nrsupers)) == NULL) - goto reterr; - - for (sup = ctd->ctd_supers, i = 0; i < nrsupers; ++i, ++sup) - { - PyObject *st; - sipTypeDef *sup_td = getGeneratedType(sup, client); - - /* - * Initialise the super-class if necessary. It will always be in - * the same module if it needs doing. - */ - if (createClassType(client, (sipClassTypeDef *)sup_td, mod_dict) < 0) - goto relbases; - - st = (PyObject *)sipTypeAsPyTypeObject(sup_td); - - Py_INCREF(st); - PyTuple_SET_ITEM(bases, i, st); - - /* - * Inherit any garbage collector code rather than look for it each - * time it is needed. - */ - if (ctd->ctd_traverse == NULL) - ctd->ctd_traverse = ((sipClassTypeDef *)sup_td)->ctd_traverse; - - if (ctd->ctd_clear == NULL) - ctd->ctd_clear = ((sipClassTypeDef *)sup_td)->ctd_clear; - } - } - - /* - * Use the explicit meta-type if there is one, otherwise use the meta-type - * of the first super-type. - */ - if (ctd->ctd_metatype >= 0) - { - const char *metatype_name = sipNameFromPool(client, ctd->ctd_metatype); - - if ((metatype = findPyType(metatype_name)) == NULL) - goto relbases; - } - else - metatype = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(bases, 0)); - - /* Create the type dictionary and populate it with any non-lazy methods. */ - if ((type_dict = createTypeDict(client)) == NULL) - goto relbases; - - if (sipTypeHasNonlazyMethod(&ctd->ctd_base)) - { - PyMethodDef *pmd = ctd->ctd_container.cod_methods; - - for (i = 0; i < ctd->ctd_container.cod_nrmethods; ++i) - { - if (isNonlazyMethod(pmd) && addMethod(type_dict, pmd) < 0) - goto reldict; - - ++pmd; - } - } - - if ((py_type = createContainerType(&ctd->ctd_container, (sipTypeDef *)ctd, bases, metatype, mod_dict, type_dict, client)) == NULL) - goto reldict; - - if (ctd->ctd_pyslots != NULL) - fix_slots((PyTypeObject *)py_type, ctd->ctd_pyslots); - - /* Handle the pickle function. */ - if (ctd->ctd_pickle != NULL) - { - static PyMethodDef md = { - "_pickle_type", pickle_type, METH_NOARGS, NULL - }; - - if (setReduce((PyTypeObject *)py_type, &md) < 0) - goto reltype; - } - - /* We can now release our references. */ - Py_DECREF(bases); - Py_DECREF(type_dict); - - return 0; - - /* Unwind after an error. */ - -reltype: - Py_DECREF(py_type); - -reldict: - Py_DECREF(type_dict); - -relbases: - Py_DECREF(bases); - -reterr: - ctd->ctd_base.td_module = NULL; - return -1; -} - - -/* - * Create a single mapped type object. - */ -static int createMappedType(sipExportedModuleDef *client, - sipMappedTypeDef *mtd, PyObject *mod_dict) -{ - PyObject *bases, *type_dict; - - /* Handle the trivial case where we have already been initialised. */ - if (mtd->mtd_base.td_module != NULL) - return 0; - - /* Set this up now to gain access to the string pool. */ - mtd->mtd_base.td_module = client; - - /* Create the tuple of super-types. */ - if ((bases = getDefaultBase()) == NULL) - goto reterr; - - /* Create the type dictionary. */ - if ((type_dict = createTypeDict(client)) == NULL) - goto relbases; - - if (createContainerType(&mtd->mtd_container, (sipTypeDef *)mtd, bases, (PyObject *)&sipWrapperType_Type, mod_dict, type_dict, client) == NULL) - goto reldict; - - /* We can now release our references. */ - Py_DECREF(bases); - Py_DECREF(type_dict); - - return 0; - - /* Unwind after an error. */ - -reldict: - Py_DECREF(type_dict); - -relbases: - Py_DECREF(bases); - -reterr: - mtd->mtd_base.td_module = NULL; - return -1; -} - - -/* - * Return the module definition for a named module. - */ -static sipExportedModuleDef *getModule(PyObject *mname_obj) -{ - PyObject *mod; - sipExportedModuleDef *em; - - /* Make sure the module is imported. */ - if ((mod = PyImport_Import(mname_obj)) == NULL) - return NULL; - - /* Find the module definition. */ - for (em = moduleList; em != NULL; em = em->em_next) - if (PyUnicode_Compare(mname_obj, em->em_nameobj) == 0) - break; - - Py_DECREF(mod); - - if (em == NULL) - PyErr_Format(PyExc_SystemError, "unable to find to find module: %U", - mname_obj); - - return em; -} - - -/* - * The type unpickler. - */ -static PyObject *unpickle_type(PyObject *obj, PyObject *args) -{ - PyObject *mname_obj, *init_args; - const char *tname; - sipExportedModuleDef *em; - int i; - - (void)obj; - - if (!PyArg_ParseTuple(args, "UsO!:_unpickle_type", &mname_obj, &tname, &PyTuple_Type, &init_args)) - return NULL; - - /* Get the module definition. */ - if ((em = getModule(mname_obj)) == NULL) - return NULL; - - /* Find the class type object. */ - for (i = 0; i < em->em_nrtypes; ++i) - { - sipTypeDef *td = em->em_types[i]; - - if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td)) - { - const char *pyname = sipPyNameOfContainer( - &((sipClassTypeDef *)td)->ctd_container, td); - - if (strcmp(pyname, tname) == 0) - return PyObject_CallObject((PyObject *)sipTypeAsPyTypeObject(td), init_args); - } - } - - PyErr_Format(PyExc_SystemError, "unable to find to find type: %s", tname); - - return NULL; -} - - -/* - * The type pickler. - */ -static PyObject *pickle_type(PyObject *obj, PyObject *args) -{ - sipExportedModuleDef *em; - - (void)args; - - /* Find the type definition and defining module. */ - for (em = moduleList; em != NULL; em = em->em_next) - { - int i; - - for (i = 0; i < em->em_nrtypes; ++i) - { - sipTypeDef *td = em->em_types[i]; - - if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td)) - if (sipTypeAsPyTypeObject(td) == Py_TYPE(obj)) - { - PyObject *init_args; - sipClassTypeDef *ctd = (sipClassTypeDef *)td; - const char *pyname = sipPyNameOfContainer(&ctd->ctd_container, td); - - /* - * Ask the handwritten pickle code for the tuple of - * arguments that will recreate the object. - */ - init_args = ctd->ctd_pickle(sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, NULL)); - - if (init_args == NULL) - return NULL; - - if (!PyTuple_Check(init_args)) - { - PyErr_Format(PyExc_TypeError, - "%%PickleCode for type %s.%s did not return a tuple", - sipNameOfModule(em), pyname); - - return NULL; - } - - return Py_BuildValue("O(OsN)", type_unpickler, - em->em_nameobj, pyname, init_args); - } - } - } - - /* We should never get here. */ - PyErr_Format(PyExc_SystemError, "attempt to pickle unknown type '%s'", - Py_TYPE(obj)->tp_name); - - return NULL; -} - - -/* - * The enum unpickler. - */ -static PyObject *unpickle_enum(PyObject *obj, PyObject *args) -{ - PyObject *mname_obj, *evalue_obj; - const char *ename; - sipExportedModuleDef *em; - int i; - - (void)obj; - - if (!PyArg_ParseTuple(args, "UsO:_unpickle_enum", &mname_obj, &ename, &evalue_obj)) - return NULL; - - /* Get the module definition. */ - if ((em = getModule(mname_obj)) == NULL) - return NULL; - - /* Find the enum type object. */ - for (i = 0; i < em->em_nrtypes; ++i) - { - sipTypeDef *td = em->em_types[i]; - - if (td != NULL && !sipTypeIsStub(td) && sipTypeIsEnum(td)) - if (strcmp(sipPyNameOfEnum((sipEnumTypeDef *)td), ename) == 0) - return PyObject_CallFunctionObjArgs((PyObject *)sipTypeAsPyTypeObject(td), evalue_obj, NULL); - } - - PyErr_Format(PyExc_SystemError, "unable to find to find enum: %s", ename); - - return NULL; -} - - -/* - * The enum pickler. - */ -static PyObject *pickle_enum(PyObject *obj, PyObject *args) -{ - sipTypeDef *td = ((sipEnumTypeObject *)Py_TYPE(obj))->type; - - (void)args; - - return Py_BuildValue("O(Osi)", enum_unpickler, td->td_module->em_nameobj, - sipPyNameOfEnum((sipEnumTypeDef *)td), (int)PyLong_AS_LONG(obj)); -} - - -/* - * Set the __reduce__method for a type. - */ -static int setReduce(PyTypeObject *type, PyMethodDef *pickler) -{ - static PyObject *rstr = NULL; - PyObject *descr; - int rc; - - if (objectify("__reduce__", &rstr) < 0) - return -1; - - /* Create the method descripter. */ - if ((descr = PyDescr_NewMethod(type, pickler)) == NULL) - return -1; - - /* - * Save the method. Note that we don't use PyObject_SetAttr() as we want - * to bypass any lazy attribute loading (which may not be safe yet). - */ - rc = PyType_Type.tp_setattro((PyObject *)type, rstr, descr); - - Py_DECREF(descr); - - return rc; -} - - -/* - * Create an enum object. - */ -static int createEnum(sipExportedModuleDef *client, sipEnumTypeDef *etd, - int enum_nr, PyObject *mod_dict) -{ - int rc; - PyObject *name, *dict, *enum_obj; - - etd->etd_base.td_module = client; - - /* Get the dictionary into which the type will be placed. */ - if (etd->etd_scope < 0) - dict = mod_dict; - else if ((dict = getScopeDict(client->em_types[etd->etd_scope], mod_dict, client)) == NULL) - return -1; - - /* Create an object corresponding to the type name. */ - if ((name = PyUnicode_FromString(sipPyNameOfEnum(etd))) == NULL) - return -1; - - /* Create the enum. */ - if (sipTypeIsEnum(&etd->etd_base)) - enum_obj = createUnscopedEnum(client, etd, name); - else - enum_obj = createScopedEnum(client, etd, enum_nr, name); - - if (enum_obj == NULL) - { - Py_DECREF(name); - return -1; - } - - /* Add the enum to the "parent" dictionary. */ - rc = PyDict_SetItem(dict, name, enum_obj); - - /* We can now release our remaining references. */ - Py_DECREF(name); - Py_DECREF(enum_obj); - - return rc; -} - - -/* - * Create an unscoped enum. - */ -static PyObject *createUnscopedEnum(sipExportedModuleDef *client, - sipEnumTypeDef *etd, PyObject *name) -{ - static PyObject *bases = NULL; - PyObject *type_dict, *args; - sipEnumTypeObject *eto; - - /* Create the base type tuple if it hasn't already been done. */ - if (bases == NULL) - if ((bases = PyTuple_Pack(1, (PyObject *)&PyLong_Type)) == NULL) - return NULL; - - /* Create the type dictionary. */ - if ((type_dict = createTypeDict(client)) == NULL) - return NULL; - - /* Create the type by calling the metatype. */ - args = PyTuple_Pack(3, name, bases, type_dict); - - Py_DECREF(type_dict); - - if (args == NULL) - return NULL; - - /* Pass the type via the back door. */ - assert(currentType == NULL); - currentType = &etd->etd_base; - eto = (sipEnumTypeObject *)PyObject_Call((PyObject *)&sipEnumType_Type, - args, NULL); - currentType = NULL; - - Py_DECREF(args); - - if (eto == NULL) - return NULL; - - if (etd->etd_pyslots != NULL) - fix_slots((PyTypeObject *)eto, etd->etd_pyslots); - - /* - * If the enum has a scope then the default __qualname__ will be incorrect. - */ - if (etd->etd_scope >= 0) - { - /* Append the name of the enum to the scope's __qualname__. */ - Py_CLEAR(eto->super.ht_qualname); - eto->super.ht_qualname = get_qualname( - client->em_types[etd->etd_scope], name); - - if (eto->super.ht_qualname == NULL) - { - Py_DECREF((PyObject *)eto); - return NULL; - } - } - - return (PyObject *)eto; -} - - -/* - * Create a scoped enum. - */ -static PyObject *createScopedEnum(sipExportedModuleDef *client, - sipEnumTypeDef *etd, int enum_nr, PyObject *name) -{ - static PyObject *enum_type = NULL, *module_arg = NULL; - static PyObject *qualname_arg = NULL; - int i, nr_members; - sipEnumMemberDef *enm; - PyObject *members, *enum_obj, *args, *kw_args; - - /* Get the enum type if we haven't done so already. */ - if (enum_type == NULL) - { - if ((enum_type = import_module_attr("enum", "IntEnum")) == NULL) - goto ret_err; - } - - /* Create a dict of the members. */ - if ((members = PyDict_New()) == NULL) - goto ret_err; - - /* - * Note that the current structures for defining scoped enums are not ideal - * as we are re-using the ones used for unscoped enums (which are designed - * to support lazy implementations). - */ - if (etd->etd_scope < 0) - { - nr_members = client->em_nrenummembers; - enm = client->em_enummembers; - } - else - { - const sipContainerDef *cod = get_container(client->em_types[etd->etd_scope]); - - nr_members = cod->cod_nrenummembers; - enm = cod->cod_enummembers; - } - - for (i = 0; i < nr_members; ++i) - { - if (enm->em_enum == enum_nr) - { - PyObject *val = PyLong_FromLong(enm->em_val); - - if (dict_set_and_discard(members, enm->em_name, val) < 0) - goto rel_members; - } - - ++enm; - } - - if ((args = PyTuple_Pack(2, name, members)) == NULL) - goto rel_members; - - if ((kw_args = PyDict_New()) == NULL) - goto rel_args; - - if (objectify("module", &module_arg) < 0) - goto rel_kw_args; - - if (PyDict_SetItem(kw_args, module_arg, client->em_nameobj) < 0) - goto rel_kw_args; - - /* - * If the enum has a scope then the default __qualname__ will be incorrect. - */ - if (etd->etd_scope >= 0) - { - int rc; - PyObject *qualname; - - if (objectify("qualname", &qualname_arg) < 0) - goto rel_kw_args; - - if ((qualname = get_qualname(client->em_types[etd->etd_scope], name)) == NULL) - goto rel_kw_args; - - rc = PyDict_SetItem(kw_args, qualname_arg, qualname); - - Py_DECREF(qualname); - - if (rc < 0) - goto rel_kw_args; - } - - if ((enum_obj = PyObject_Call(enum_type, args, kw_args)) == NULL) - goto rel_kw_args; - - Py_DECREF(kw_args); - Py_DECREF(args); - Py_DECREF(members); - - /* Note that it isn't actually a PyTypeObject. */ - etd->etd_base.td_py_type = (PyTypeObject *)enum_obj; - - return enum_obj; - - /* Unwind on errors. */ - -rel_kw_args: - Py_DECREF(kw_args); - -rel_args: - Py_DECREF(args); - -rel_members: - Py_DECREF(members); - -ret_err: - return NULL; -} - - -/* - * Create a type dictionary for dynamic type being created in a module. - */ -static PyObject *createTypeDict(sipExportedModuleDef *em) -{ - static PyObject *mstr = NULL; - PyObject *dict; - - if (objectify("__module__", &mstr) < 0) - return NULL; - - /* Create the dictionary. */ - if ((dict = PyDict_New()) == NULL) - return NULL; - - /* We need to set the module name as an attribute for dynamic types. */ - if (PyDict_SetItem(dict, mstr, em->em_nameobj) < 0) - { - Py_DECREF(dict); - return NULL; - } - - return dict; -} - - -/* - * Convert an ASCII string to a Python object if it hasn't already been done. - */ -static int objectify(const char *s, PyObject **objp) -{ - if (*objp == NULL) - if ((*objp = PyUnicode_FromString(s)) == NULL) - return -1; - - return 0; -} - - -/* - * Add a set of static instances to a dictionary. - */ -static int addInstances(PyObject *dict, sipInstancesDef *id) -{ - if (id->id_type != NULL && addTypeInstances(dict, id->id_type) < 0) - return -1; - - if (id->id_voidp != NULL && addVoidPtrInstances(dict,id->id_voidp) < 0) - return -1; - - if (id->id_char != NULL && addCharInstances(dict,id->id_char) < 0) - return -1; - - if (id->id_string != NULL && addStringInstances(dict,id->id_string) < 0) - return -1; - - if (id->id_int != NULL && addIntInstances(dict, id->id_int) < 0) - return -1; - - if (id->id_long != NULL && addLongInstances(dict,id->id_long) < 0) - return -1; - - if (id->id_ulong != NULL && addUnsignedLongInstances(dict, id->id_ulong) < 0) - return -1; - - if (id->id_llong != NULL && addLongLongInstances(dict, id->id_llong) < 0) - return -1; - - if (id->id_ullong != NULL && addUnsignedLongLongInstances(dict, id->id_ullong) < 0) - return -1; - - if (id->id_double != NULL && addDoubleInstances(dict,id->id_double) < 0) - return -1; - - return 0; -} - - -/* - * Get "self" from the argument tuple for a method called as - * Class.Method(self, ...) rather than self.Method(...). - */ -static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr, - sipSimpleWrapper **selfp) -{ - PyObject *self; - - /* Get self from the argument tuple. */ - - if (argnr >= PyTuple_GET_SIZE(args)) - return FALSE; - - self = PyTuple_GET_ITEM(args, argnr); - - if (!PyObject_TypeCheck(self, sipTypeAsPyTypeObject(td))) - return FALSE; - - *selfp = (sipSimpleWrapper *)self; - - return TRUE; -} - - -/* - * Return non-zero if a method is non-lazy, ie. it must be added to the type - * when it is created. - */ -static int isNonlazyMethod(PyMethodDef *pmd) -{ - static const char *lazy[] = { - "__getattribute__", - "__getattr__", - "__enter__", - "__exit__", - "__aenter__", - "__aexit__", - NULL - }; - - const char **l; - - for (l = lazy; *l != NULL; ++l) - if (strcmp(pmd->ml_name, *l) == 0) - return TRUE; - - return FALSE; -} - - -/* - * Add a method to a dictionary. - */ -static int addMethod(PyObject *dict, PyMethodDef *pmd) -{ - PyObject *descr = sipMethodDescr_New(pmd); - - return dict_set_and_discard(dict, pmd->ml_name, descr); -} - - -/* - * Populate a container's type dictionary. - */ -static int add_lazy_container_attrs(sipTypeDef *td, sipContainerDef *cod, - PyObject *dict) -{ - int i; - PyMethodDef *pmd; - sipEnumMemberDef *enm; - sipVariableDef *vd; - - /* Do the methods. */ - for (pmd = cod->cod_methods, i = 0; i < cod->cod_nrmethods; ++i, ++pmd) - { - /* Non-lazy methods will already have been handled. */ - if (!sipTypeHasNonlazyMethod(td) || !isNonlazyMethod(pmd)) - { - if (addMethod(dict, pmd) < 0) - return -1; - } - } - - /* Do the unscoped enum members. */ - for (enm = cod->cod_enummembers, i = 0; i < cod->cod_nrenummembers; ++i, ++enm) - { - PyObject *val; - - if (enm->em_enum < 0) - { - /* It's an unnamed unscoped enum. */ - val = PyLong_FromLong(enm->em_val); - } - else - { - sipTypeDef *etd = td->td_module->em_types[enm->em_enum]; - - if (sipTypeIsScopedEnum(etd)) - continue; - - val = sip_api_convert_from_enum(enm->em_val, etd); - } - - if (dict_set_and_discard(dict, enm->em_name, val) < 0) - return -1; - } - - /* Do the variables. */ - for (vd = cod->cod_variables, i = 0; i < cod->cod_nrvariables; ++i, ++vd) - { - PyObject *descr; - - if (vd->vd_type == PropertyVariable) - descr = create_property(vd); - else - descr = sipVariableDescr_New(vd, td, cod); - - if (dict_set_and_discard(dict, vd->vd_name, descr) < 0) - return -1; - } - - return 0; -} - - -/* - * Create a Python property object from the SIP generated structure. - */ -static PyObject *create_property(sipVariableDef *vd) -{ - PyObject *descr, *fget, *fset, *fdel, *doc; - - descr = fget = fset = fdel = doc = NULL; - - if ((fget = create_function(vd->vd_getter)) == NULL) - goto done; - - if ((fset = create_function(vd->vd_setter)) == NULL) - goto done; - - if ((fdel = create_function(vd->vd_deleter)) == NULL) - goto done; - - if (vd->vd_docstring == NULL) - { - doc = Py_None; - Py_INCREF(doc); - } - else if ((doc = PyUnicode_FromString(vd->vd_docstring)) == NULL) - { - goto done; - } - - descr = PyObject_CallFunctionObjArgs((PyObject *)&PyProperty_Type, fget, - fset, fdel, doc, NULL); - -done: - Py_XDECREF(fget); - Py_XDECREF(fset); - Py_XDECREF(fdel); - Py_XDECREF(doc); - - return descr; -} - - -/* - * Return a PyCFunction as an object or Py_None if there isn't one. - */ -static PyObject *create_function(PyMethodDef *ml) -{ - if (ml != NULL) - return PyCFunction_New(ml, NULL); - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Populate a type dictionary with all lazy attributes if it hasn't already - * been done. - */ -static int add_lazy_attrs(sipTypeDef *td) -{ - sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td); - PyObject *dict; - sipAttrGetter *ag; - - /* Handle the trivial case. */ - if (wt->wt_dict_complete) - return 0; - - dict = ((PyTypeObject *)wt)->tp_dict; - - if (sipTypeIsMapped(td)) - { - if (add_lazy_container_attrs(td, &((sipMappedTypeDef *)td)->mtd_container, dict) < 0) - return -1; - } - else - { - sipClassTypeDef *nsx; - - /* Search the possible linked list of namespace extenders. */ - for (nsx = (sipClassTypeDef *)td; nsx != NULL; nsx = nsx->ctd_nsextender) - if (add_lazy_container_attrs((sipTypeDef *)nsx, &nsx->ctd_container, dict) < 0) - return -1; - } - - /* - * Get any lazy attributes from registered getters. This must be done last - * to allow any existing attributes to be replaced. - */ - /* TODO: Deprecate this mechanism in favour of an event handler. */ - for (ag = sipAttrGetters; ag != NULL; ag = ag->next) - if (ag->type == NULL || PyType_IsSubtype((PyTypeObject *)wt, ag->type)) - if (ag->getter(td, dict) < 0) - return -1; - - wt->wt_dict_complete = TRUE; - - PyType_Modified((PyTypeObject *)wt); - - return 0; -} - - -/* - * Populate the type dictionary and all its super-types. - */ -static int add_all_lazy_attrs(sipTypeDef *td) -{ - if (td == NULL) - return 0; - - if (add_lazy_attrs(td) < 0) - return -1; - - if (sipTypeIsClass(td)) - { - sipClassTypeDef *ctd = (sipClassTypeDef *)td; - sipEncodedTypeDef *sup; - - if ((sup = ctd->ctd_supers) != NULL) - do - { - sipTypeDef *sup_td = getGeneratedType(sup, td->td_module); - - if (add_all_lazy_attrs(sup_td) < 0) - return -1; - } - while (!sup++->sc_flag); - } - - return 0; -} - - -/* - * Return the generated type structure corresponding to the given Python type - * object. - */ -static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type) -{ - if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type)) - return ((sipWrapperType *)py_type)->wt_td; - - if (PyObject_TypeCheck((PyObject *)py_type, &sipEnumType_Type)) - return ((sipEnumTypeObject *)py_type)->type; - - return NULL; -} - - -/* - * Return the generated type structure corresponding to the scope of the given - * type. - */ -static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td) -{ - if (sipTypeIsEnum(td) || sipTypeIsScopedEnum(td)) - { - const sipEnumTypeDef *etd = (const sipEnumTypeDef *)td; - - if (etd->etd_scope >= 0) - return td->td_module->em_types[etd->etd_scope]; - } - else - { - const sipContainerDef *cod; - - if (sipTypeIsMapped(td)) - cod = &((const sipMappedTypeDef *)td)->mtd_container; - else - cod = &((const sipClassTypeDef *)td)->ctd_container; - - if (!cod->cod_scope.sc_flag) - return getGeneratedType(&cod->cod_scope, td->td_module); - } - - return NULL; -} - - -/* - * Return TRUE if an object can be converted to a named enum. - */ -static int sip_api_can_convert_to_enum(PyObject *obj, const sipTypeDef *td) -{ - /* Remove in v5.1. */ - - assert(sipTypeIsEnum(td)); - - /* If the object is an enum then it must be the right enum. */ - if (PyObject_TypeCheck((PyObject *)Py_TYPE(obj), &sipEnumType_Type)) - return (PyObject_TypeCheck(obj, sipTypeAsPyTypeObject(td))); - - return PyLong_Check(obj); -} - - -/* - * Convert a Python object implementing a named enum to an integer value. - */ -static int sip_api_convert_to_enum(PyObject *obj, const sipTypeDef *td) -{ - return convert_to_enum(obj, td, TRUE); -} - - -/* - * Convert a Python object implementing a named enum (or, optionally, an int) - * to an integer value. - */ -static int convert_to_enum(PyObject *obj, const sipTypeDef *td, int allow_int) -{ - int val; - - assert(sipTypeIsEnum(td) || sipTypeIsScopedEnum(td)); - - if (sipTypeIsScopedEnum(td)) - { - static PyObject *value = NULL; - PyObject *val_obj; - - if (PyObject_IsInstance(obj, (PyObject *)sipTypeAsPyTypeObject(td)) <= 0) - { - enum_expected(obj, td); - return -1; - } - - if (objectify("value", &value) < 0) - return -1; - - if ((val_obj = PyObject_GetAttr(obj, value)) == NULL) - return -1; - - /* This will never overflow. */ - val = long_as_nonoverflow_int(val_obj); - - Py_DECREF(val_obj); - } - else - { - if (PyObject_TypeCheck((PyObject *)Py_TYPE(obj), &sipEnumType_Type)) - { - if (!PyObject_TypeCheck(obj, sipTypeAsPyTypeObject(td))) - { - enum_expected(obj, td); - return -1; - } - - /* This will never overflow. */ - val = long_as_nonoverflow_int(obj); - } - else if (allow_int && PyLong_Check(obj)) - { - val = long_as_nonoverflow_int(obj); - } - else - { - enum_expected(obj, td); - return -1; - } - } - - return val; -} - - -/* - * Raise an exception when failing to convert an enum because of its type. - */ -static void enum_expected(PyObject *obj, const sipTypeDef *td) -{ - PyErr_Format(PyExc_TypeError, "a member of enum '%s' is expected not '%s'", - sipPyNameOfEnum((sipEnumTypeDef *)td), Py_TYPE(obj)->tp_name); -} - - -/* Convert to a C/C++ int while checking for overflow. */ -static int long_as_nonoverflow_int(PyObject *val_obj) -{ - int old_overflow, val; - - old_overflow = sip_api_enable_overflow_checking(TRUE); - val = sip_api_long_as_int(val_obj); - sip_api_enable_overflow_checking(old_overflow); - - return val; -} - - -/* - * Create a Python object for a member of a named enum. - */ -static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td) -{ - assert(sipTypeIsEnum(td) || sipTypeIsScopedEnum(td)); - - return PyObject_CallFunction((PyObject *)sipTypeAsPyTypeObject(td), "(i)", - eval); -} - - -/* - * Register a getter for unknown attributes. - */ -static int sip_api_register_attribute_getter(const sipTypeDef *td, - sipAttrGetterFunc getter) -{ - sipAttrGetter *ag = sip_api_malloc(sizeof (sipAttrGetter)); - - if (ag == NULL) - return -1; - - ag->type = sipTypeAsPyTypeObject(td); - ag->getter = getter; - ag->next = sipAttrGetters; - - sipAttrGetters = ag; - - return 0; -} - - -/* - * Register a proxy resolver. - */ -static int sip_api_register_proxy_resolver(const sipTypeDef *td, - sipProxyResolverFunc resolver) -{ - sipProxyResolver *pr = sip_api_malloc(sizeof (sipProxyResolver)); - - if (pr == NULL) - return -1; - - pr->td = td; - pr->resolver = resolver; - pr->next = proxyResolvers; - - proxyResolvers = pr; - - return 0; -} - - -/* - * Report a function with invalid argument types. - */ -static void sip_api_no_function(PyObject *parseErr, const char *func, - const char *doc) -{ - sip_api_no_method(parseErr, NULL, func, doc); -} - - -/* - * Report a method/function/signal with invalid argument types. - */ -static void sip_api_no_method(PyObject *parseErr, const char *scope, - const char *method, const char *doc) -{ - const char *sep = "."; - - if (scope == NULL) - scope = ++sep; - - if (parseErr == NULL) - { - /* - * If we have got this far without trying a parse then there must be no - * overloads. - */ - PyErr_Format(PyExc_TypeError, "%s%s%s() is a private method", scope, - sep, method); - } - else if (PyList_Check(parseErr)) - { - PyObject *exc; - - /* There is an entry for each overload that was tried. */ - if (PyList_GET_SIZE(parseErr) == 1) - { - PyObject *detail = detail_FromFailure( - PyList_GET_ITEM(parseErr, 0)); - - if (detail != NULL) - { - if (doc != NULL) - { - PyObject *doc_obj = signature_FromDocstring(doc, 0); - - if (doc_obj != NULL) - { - exc = PyUnicode_FromFormat("%U: %U", doc_obj, detail); - Py_DECREF(doc_obj); - } - else - { - exc = NULL; - } - } - else - { - exc = PyUnicode_FromFormat("%s%s%s(): %U", scope, sep, - method, detail); - } - - Py_DECREF(detail); - } - else - { - exc = NULL; - } - } - else - { - static const char *summary = "arguments did not match any overloaded call:"; - - Py_ssize_t i; - - if (doc != NULL) - exc = PyUnicode_FromString(summary); - else - exc = PyUnicode_FromFormat("%s%s%s(): %s", scope, sep, method, - summary); - - for (i = 0; i < PyList_GET_SIZE(parseErr); ++i) - { - PyObject *failure; - PyObject *detail = detail_FromFailure( - PyList_GET_ITEM(parseErr, i)); - - if (detail != NULL) - { - if (doc != NULL) - { - PyObject *doc_obj = signature_FromDocstring(doc, i); - - if (doc_obj != NULL) - { - failure = PyUnicode_FromFormat("\n %U: %U", - doc_obj, detail); - - Py_DECREF(doc_obj); - } - else - { - Py_XDECREF(exc); - exc = NULL; - break; - } - } - else - { - failure = PyUnicode_FromFormat("\n overload %zd: %U", - i + 1, detail); - } - - Py_DECREF(detail); - - PyUnicode_AppendAndDel(&exc, failure); - } - else - { - Py_XDECREF(exc); - exc = NULL; - break; - } - } - } - - if (exc != NULL) - { - PyErr_SetObject(PyExc_TypeError, exc); - Py_DECREF(exc); - } - } - else - { - /* - * None is used as a marker to say that an exception has already been - * raised. - */ - assert(parseErr == Py_None); - } - - Py_XDECREF(parseErr); -} - - -/* - * Return a string/unicode object extracted from a particular line of a - * docstring. - */ -static PyObject *signature_FromDocstring(const char *doc, Py_ssize_t line) -{ - const char *eol; - Py_ssize_t size = 0; - - /* - * Find the start of the line. If there is a non-default versioned - * overload that has been enabled then it won't have an entry in the - * docstring. This means that the returned signature may be incorrect. - */ - while (line-- > 0) - { - const char *next = strchr(doc, '\n'); - - if (next == NULL) - break; - - doc = next + 1; - } - - /* Find the last closing parenthesis. */ - for (eol = doc; *eol != '\n' && *eol != '\0'; ++eol) - if (*eol == ')') - size = eol - doc + 1; - - return PyUnicode_FromStringAndSize(doc, size); -} - - -/* - * Return a string/unicode object that describes the given failure. - */ -static PyObject *detail_FromFailure(PyObject *failure_obj) -{ - sipParseFailure *failure; - PyObject *detail; - - failure = (sipParseFailure *)PyCapsule_GetPointer(failure_obj, NULL); - - switch (failure->reason) - { - case Unbound: - detail = PyUnicode_FromFormat( - "first argument of unbound method must have type '%s'", - failure->detail_str); - break; - - case TooFew: - detail = PyUnicode_FromString("not enough arguments"); - break; - - case TooMany: - detail = PyUnicode_FromString("too many arguments"); - break; - - case KeywordNotString: - detail = PyUnicode_FromFormat( - "%S keyword argument name is not a string", - failure->detail_obj); - break; - - case UnknownKeyword: - detail = PyUnicode_FromFormat("'%U' is not a valid keyword argument", - failure->detail_obj); - break; - - case Duplicate: - detail = PyUnicode_FromFormat( - "'%U' has already been given as a positional argument", - failure->detail_obj); - break; - - case WrongType: - if (failure->arg_nr >= 0) - detail = bad_type_str(failure->arg_nr, failure->detail_obj); - else - detail = PyUnicode_FromFormat( - "argument '%s' has unexpected type '%s'", - failure->arg_name, Py_TYPE(failure->detail_obj)->tp_name); - - break; - - case Exception: - detail = failure->detail_obj; - - if (detail) - { - Py_INCREF(detail); - break; - } - - /* Drop through. */ - - default: - detail = PyUnicode_FromString("unknown reason"); - } - - return detail; -} - - -/* - * Report an abstract method called with an unbound self. - */ -static void sip_api_abstract_method(const char *classname, const char *method) -{ - PyErr_Format(PyExc_TypeError, - "%s.%s() is abstract and cannot be called as an unbound method", - classname, method); -} - - -/* - * Report a deprecated class or method. - */ -int sip_api_deprecated(const char *classname, const char *method) -{ - char buf[100]; - - if (classname == NULL) - PyOS_snprintf(buf, sizeof (buf), "%s() is deprecated", method); - else if (method == NULL) - PyOS_snprintf(buf, sizeof (buf), "%s constructor is deprecated", - classname); - else - PyOS_snprintf(buf, sizeof (buf), "%s.%s() is deprecated", classname, - method); - - return PyErr_WarnEx(PyExc_DeprecationWarning, buf, 1); -} - - -/* - * Report a bad operator argument. Only a small subset of operators need to - * be handled (those that don't return Py_NotImplemented). - */ -static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg, - sipPySlotType st) -{ - const char *sn = NULL; - - /* Try and get the text to match a Python exception. */ - - switch (st) - { - case concat_slot: - case iconcat_slot: - PyErr_Format(PyExc_TypeError, - "cannot concatenate '%s' and '%s' objects", - Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name); - break; - - case repeat_slot: - sn = "*"; - break; - - case irepeat_slot: - sn = "*="; - break; - - default: - sn = "unknown"; - } - - if (sn != NULL) - PyErr_Format(PyExc_TypeError, - "unsupported operand type(s) for %s: '%s' and '%s'", sn, - Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name); -} - - -/* - * Report a sequence length that does not match the length of a slice. - */ -static void sip_api_bad_length_for_slice(Py_ssize_t seqlen, - Py_ssize_t slicelen) -{ - PyErr_Format(PyExc_ValueError, - "attempt to assign sequence of size %zd to slice of size %zd", - seqlen, slicelen); -} - - -/* - * Report a Python object that cannot be converted to a particular class. - */ -static void sip_api_bad_class(const char *classname) -{ - PyErr_Format(PyExc_TypeError, - "cannot convert Python object to an instance of %s", classname); -} - - -/* - * Report a Python member function with an unexpected result. - */ -static void sip_api_bad_catcher_result(PyObject *method) -{ - PyObject *mname, *etype, *evalue, *etraceback; - - /* - * Get the current exception object if there is one. Its string - * representation will be used as the detail of a new exception. - */ - PyErr_Fetch(&etype, &evalue, &etraceback); - PyErr_NormalizeException(&etype, &evalue, &etraceback); - Py_XDECREF(etraceback); - - /* - * This is part of the public API so we make no assumptions about the - * method object. - */ - if (!PyMethod_Check(method) || - PyMethod_GET_FUNCTION(method) == NULL || - !PyFunction_Check(PyMethod_GET_FUNCTION(method)) || - PyMethod_GET_SELF(method) == NULL) - { - PyErr_Format(PyExc_TypeError, - "invalid argument to sipBadCatcherResult()"); - return; - } - - mname = ((PyFunctionObject *)PyMethod_GET_FUNCTION(method))->func_name; - - if (evalue != NULL) - { - PyErr_Format(etype, "invalid result from %s.%U(), %S", - Py_TYPE(PyMethod_GET_SELF(method))->tp_name, mname, evalue); - Py_DECREF(evalue); - } - else - { - PyErr_Format(PyExc_TypeError, "invalid result from %s.%U()", - Py_TYPE(PyMethod_GET_SELF(method))->tp_name, mname); - } - - Py_XDECREF(etype); -} - - -/* - * Transfer ownership of a class instance to Python from C/C++. - */ -static void sip_api_transfer_back(PyObject *self) -{ - if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) - { - sipSimpleWrapper *sw = (sipSimpleWrapper *)self; - - if (sipCppHasRef(sw)) - { - sipResetCppHasRef(sw); - Py_DECREF(sw); - } - else - { - removeFromParent((sipWrapper *)sw); - } - - sipSetPyOwned(sw); - } -} - - -/* - * Break the association of a C++ owned Python object with any parent. This is - * deprecated because it is the equivalent of sip_api_transfer_to(self, NULL). - */ -static void sip_api_transfer_break(PyObject *self) -{ - /* Remove in v5.1. */ - - if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) - { - sipSimpleWrapper *sw = (sipSimpleWrapper *)self; - - if (sipCppHasRef(sw)) - { - sipResetCppHasRef(sw); - Py_DECREF(sw); - } - else - { - removeFromParent((sipWrapper *)sw); - } - } -} - - -/* - * Transfer ownership of a class instance to C/C++ from Python. - */ -static void sip_api_transfer_to(PyObject *self, PyObject *owner) -{ - /* - * There is a legitimate case where we try to transfer a PyObject that - * may not be a SIP generated class. The virtual handler code calls - * this function to keep the C/C++ instance alive when it gets rid of - * the Python object returned by the Python method. A class may have - * handwritten code that converts a regular Python type - so we can't - * assume that we can simply cast to sipWrapper. - */ - if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) - { - sipSimpleWrapper *sw = (sipSimpleWrapper *)self; - - if (owner == NULL) - { - /* There is no owner. */ - - if (sipCppHasRef(sw)) - { - sipResetCppHasRef(sw); - } - else - { - Py_INCREF(sw); - removeFromParent((sipWrapper *)sw); - sipResetPyOwned(sw); - } - - Py_DECREF(sw); - } - else if (owner == Py_None) - { - /* - * The owner is a C++ instance and not a Python object (ie. there - * is no parent) so there is an explicit extra reference to keep - * this Python object alive. Note that there is no way to - * specify this from a .sip file - it is useful when embedding in - * C/C++ applications. - */ - - if (!sipCppHasRef(sw)) - { - Py_INCREF(sw); - removeFromParent((sipWrapper *)sw); - sipResetPyOwned(sw); - - sipSetCppHasRef(sw); - } - } - else if (PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type)) - { - /* - * The owner is a Python object (ie. the C++ instance that the - * Python object wraps). - */ - - if (sipCppHasRef(sw)) - { - sipResetCppHasRef(sw); - } - else - { - Py_INCREF(sw); - removeFromParent((sipWrapper *)sw); - sipResetPyOwned(sw); - } - - addToParent((sipWrapper *)sw, (sipWrapper *)owner); - - Py_DECREF(sw); - } - } -} - - -/* - * Add a license to a dictionary. - */ -static int addLicense(PyObject *dict,sipLicenseDef *lc) -{ - int rc; - PyObject *ldict, *proxy, *o; - - /* Convert the strings we use to objects if not already done. */ - - if (objectify("__license__", &licenseName) < 0) - return -1; - - if (objectify("Licensee", &licenseeName) < 0) - return -1; - - if (objectify("Type", &typeName) < 0) - return -1; - - if (objectify("Timestamp", ×tampName) < 0) - return -1; - - if (objectify("Signature", &signatureName) < 0) - return -1; - - /* We use a dictionary to hold the license information. */ - if ((ldict = PyDict_New()) == NULL) - return -1; - - /* The license type is compulsory, the rest are optional. */ - if (lc->lc_type == NULL) - goto deldict; - - if ((o = PyUnicode_FromString(lc->lc_type)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,typeName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - - if (lc->lc_licensee != NULL) - { - if ((o = PyUnicode_FromString(lc->lc_licensee)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,licenseeName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - } - - if (lc->lc_timestamp != NULL) - { - if ((o = PyUnicode_FromString(lc->lc_timestamp)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,timestampName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - } - - if (lc->lc_signature != NULL) - { - if ((o = PyUnicode_FromString(lc->lc_signature)) == NULL) - goto deldict; - - rc = PyDict_SetItem(ldict,signatureName,o); - Py_DECREF(o); - - if (rc < 0) - goto deldict; - } - - /* Create a read-only proxy. */ - if ((proxy = PyDictProxy_New(ldict)) == NULL) - goto deldict; - - Py_DECREF(ldict); - - rc = PyDict_SetItem(dict, licenseName, proxy); - Py_DECREF(proxy); - - return rc; - -deldict: - Py_DECREF(ldict); - - return -1; -} - - -/* - * Add the void pointer instances to a dictionary. - */ -static int addVoidPtrInstances(PyObject *dict,sipVoidPtrInstanceDef *vi) -{ - while (vi->vi_name != NULL) - { - PyObject *w = sip_api_convert_from_void_ptr(vi->vi_val); - - if (dict_set_and_discard(dict, vi->vi_name, w) < 0) - return -1; - - ++vi; - } - - return 0; -} - - -/* - * Add the char instances to a dictionary. - */ -static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci) -{ - while (ci->ci_name != NULL) - { - PyObject *w; - - switch (ci->ci_encoding) - { - case 'A': - w = PyUnicode_DecodeASCII(&ci->ci_val, 1, NULL); - break; - - case 'L': - w = PyUnicode_DecodeLatin1(&ci->ci_val, 1, NULL); - break; - - case '8': - w = PyUnicode_FromStringAndSize(&ci->ci_val, 1); - break; - - default: - w = PyBytes_FromStringAndSize(&ci->ci_val, 1); - } - - if (dict_set_and_discard(dict, ci->ci_name, w) < 0) - return -1; - - ++ci; - } - - return 0; -} - - -/* - * Add the string instances to a dictionary. - */ -static int addStringInstances(PyObject *dict, sipStringInstanceDef *si) -{ - while (si->si_name != NULL) - { - PyObject *w; - - switch (si->si_encoding) - { - case 'A': - w = PyUnicode_DecodeASCII(si->si_val, strlen(si->si_val), NULL); - break; - - case 'L': - w = PyUnicode_DecodeLatin1(si->si_val, strlen(si->si_val), NULL); - break; - - case '8': - w = PyUnicode_FromString(si->si_val); - break; - - case 'w': - /* The hack for wchar_t. */ -#if defined(HAVE_WCHAR_H) - w = PyUnicode_FromWideChar((const wchar_t *)si->si_val, 1); - break; -#else - raiseNoWChar(); - return -1; -#endif - - case 'W': - /* The hack for wchar_t*. */ -#if defined(HAVE_WCHAR_H) - w = PyUnicode_FromWideChar((const wchar_t *)si->si_val, - wcslen((const wchar_t *)si->si_val)); - break; -#else - raiseNoWChar(); - return -1; -#endif - - default: - w = PyBytes_FromString(si->si_val); - } - - if (dict_set_and_discard(dict, si->si_name, w) < 0) - return -1; - - ++si; - } - - return 0; -} - - -/* - * Add the int instances to a dictionary. - */ -static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii) -{ - while (ii->ii_name != NULL) - { - PyObject *w = PyLong_FromLong(ii->ii_val); - - if (dict_set_and_discard(dict, ii->ii_name, w) < 0) - return -1; - - ++ii; - } - - return 0; -} - - -/* - * Add the long instances to a dictionary. - */ -static int addLongInstances(PyObject *dict,sipLongInstanceDef *li) -{ - while (li->li_name != NULL) - { - PyObject *w = PyLong_FromLong(li->li_val); - - if (dict_set_and_discard(dict, li->li_name, w) < 0) - return -1; - - ++li; - } - - return 0; -} - - -/* - * Add the unsigned long instances to a dictionary. - */ -static int addUnsignedLongInstances(PyObject *dict, sipUnsignedLongInstanceDef *uli) -{ - while (uli->uli_name != NULL) - { - PyObject *w = PyLong_FromUnsignedLong(uli->uli_val); - - if (dict_set_and_discard(dict, uli->uli_name, w) < 0) - return -1; - - ++uli; - } - - return 0; -} - - -/* - * Add the long long instances to a dictionary. - */ -static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli) -{ - while (lli->lli_name != NULL) - { - PyObject *w; - -#if defined(HAVE_LONG_LONG) - w = PyLong_FromLongLong(lli->lli_val); -#else - w = PyLong_FromLong(lli->lli_val); -#endif - - if (dict_set_and_discard(dict, lli->lli_name, w) < 0) - return -1; - - ++lli; - } - - return 0; -} - - -/* - * Add the unsigned long long instances to a dictionary. - */ -static int addUnsignedLongLongInstances(PyObject *dict, sipUnsignedLongLongInstanceDef *ulli) -{ - while (ulli->ulli_name != NULL) - { - PyObject *w; - -#if defined(HAVE_LONG_LONG) - w = PyLong_FromUnsignedLongLong(ulli->ulli_val); -#else - w = PyLong_FromUnsignedLong(ulli->ulli_val); -#endif - - if (dict_set_and_discard(dict, ulli->ulli_name, w) < 0) - return -1; - - ++ulli; - } - - return 0; -} - - -/* - * Add the double instances to a dictionary. - */ -static int addDoubleInstances(PyObject *dict,sipDoubleInstanceDef *di) -{ - while (di->di_name != NULL) - { - PyObject *w = PyFloat_FromDouble(di->di_val); - - if (dict_set_and_discard(dict, di->di_name, w) < 0) - return -1; - - ++di; - } - - return 0; -} - - -/* - * Wrap a set of type instances and add them to a dictionary. - */ -static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti) -{ - while (ti->ti_name != NULL) - { - if (addSingleTypeInstance(dict, ti->ti_name, ti->ti_ptr, *ti->ti_type, ti->ti_flags) < 0) - return -1; - - ++ti; - } - - return 0; -} - - -/* - * Wrap a single type instance and add it to a dictionary. - */ -static int addSingleTypeInstance(PyObject *dict, const char *name, - void *cppPtr, const sipTypeDef *td, int initflags) -{ - PyObject *obj; - - if (sipTypeIsEnum(td) || sipTypeIsScopedEnum(td)) - { - obj = sip_api_convert_from_enum(*(int *)cppPtr, td); - } - else - { - sipConvertFromFunc cfrom; - - cppPtr = resolve_proxy(td, cppPtr); - - cfrom = get_from_convertor(td); - - if (cfrom != NULL) - obj = cfrom(cppPtr, NULL); - else - obj = wrap_simple_instance(cppPtr, td, NULL, initflags); - } - - return dict_set_and_discard(dict, name, obj); -} - - -/* - * Convert a type instance and add it to a dictionary. - */ -static int sip_api_add_type_instance(PyObject *dict, const char *name, - void *cppPtr, const sipTypeDef *td) -{ - return addSingleTypeInstance(getDictFromObject(dict), name, cppPtr, td, 0); -} - - -/* - * Return the instance dictionary for an object if it is a wrapped type. - * Otherwise assume that it is a module dictionary. - */ -static PyObject *getDictFromObject(PyObject *obj) -{ - if (PyObject_TypeCheck(obj, (PyTypeObject *)&sipWrapperType_Type)) - obj = ((PyTypeObject *)obj)->tp_dict; - - return obj; -} - - -/* - * Return a Python reimplementation corresponding to a C/C++ virtual function, - * if any. If one was found then the GIL is acquired. This is deprecated, use - * sip_api_is_python_method_12_8() instead. - */ -static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper *sipSelf, const char *cname, const char *mname) -{ - return sip_api_is_py_method_12_8(gil, pymc, &sipSelf, cname, mname); -} - - -/* - * Return a Python reimplementation corresponding to a C/C++ virtual function, - * if any. If one was found then the GIL is acquired. - */ -static PyObject *sip_api_is_py_method_12_8(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper **sipSelfp, const char *cname, const char *mname) -{ - sipSimpleWrapper *sipSelf; - PyObject *mname_obj, *reimp, *mro, *cls; - Py_ssize_t i; - - /* - * This is the most common case (where there is no Python reimplementation) - * so we take a fast shortcut without acquiring the GIL. - */ - if (*pymc != 0) - return NULL; - - /* We might still have C++ going after the interpreter has gone. */ - if (sipInterpreter == NULL) - return NULL; - -#ifdef WITH_THREAD - *gil = PyGILState_Ensure(); -#endif - - /* Only read this when we have the GIL. */ - sipSelf = *sipSelfp; - - /* - * It's possible that the Python object has been deleted but the underlying - * C++ instance is still working and trying to handle virtual functions. - * Alternatively, an instance has started handling virtual functions before - * its ctor has returned. In either case say there is no Python - * reimplementation. - */ - if (sipSelf != NULL) - sipSelf = deref_mixin(sipSelf); - - if (sipSelf == NULL) - goto release_gil; - - /* - * It's possible that the object's type's tp_mro is NULL. A possible - * circumstance is when a type has been created dynamically and the only - * reference to it is the single instance of the type which is in the - * process of being garbage collected. - */ - cls = (PyObject *)Py_TYPE(sipSelf); - mro = ((PyTypeObject *)cls)->tp_mro; - - if (mro == NULL) - goto release_gil; - - /* Get any reimplementation. */ - - if ((mname_obj = PyUnicode_FromString(mname)) == NULL) - goto release_gil; - - /* - * We don't use PyObject_GetAttr() because that might find the generated - * C function before a reimplementation defined in a mixin (ie. later in - * the MRO). However that means we must explicitly check that the class - * hierarchy is fully initialised. - */ - if (add_all_lazy_attrs(((sipWrapperType *)Py_TYPE(sipSelf))->wt_td) < 0) - { - Py_DECREF(mname_obj); - goto release_gil; - } - - if (sipSelf->dict != NULL) - { - /* Check the instance dictionary in case it has been monkey patched. */ - if ((reimp = PyDict_GetItem(sipSelf->dict, mname_obj)) != NULL && PyCallable_Check(reimp)) - { - Py_DECREF(mname_obj); - - Py_INCREF(reimp); - return reimp; - } - } - - assert(PyTuple_Check(mro)); - - reimp = NULL; - - for (i = 0; i < PyTuple_GET_SIZE(mro); ++i) - { - PyObject *cls_dict, *cls_attr; - - cls = PyTuple_GET_ITEM(mro, i); - - cls_dict = ((PyTypeObject *)cls)->tp_dict; - - /* - * Check any possible reimplementation is not the wrapped C++ method or - * a default special method implementation. - */ - if (cls_dict != NULL && (cls_attr = PyDict_GetItem(cls_dict, mname_obj)) != NULL && Py_TYPE(cls_attr) != &sipMethodDescr_Type && Py_TYPE(cls_attr) != &PyWrapperDescr_Type) - { - reimp = cls_attr; - break; - } - } - - Py_DECREF(mname_obj); - - if (reimp != NULL) - { - /* - * Emulate the behaviour of a descriptor to make sure we return a bound - * method. - */ - if (PyMethod_Check(reimp)) - { - /* It's already a method but make sure it is bound. */ - if (PyMethod_GET_SELF(reimp) != NULL) - Py_INCREF(reimp); - else - reimp = PyMethod_New(PyMethod_GET_FUNCTION(reimp), - (PyObject *)sipSelf); - } - else if (PyFunction_Check(reimp)) - { - reimp = PyMethod_New(reimp, (PyObject *)sipSelf); - } - else if (Py_TYPE(reimp)->tp_descr_get) - { - /* It is a descriptor, so assume it will do the right thing. */ - reimp = Py_TYPE(reimp)->tp_descr_get(reimp, (PyObject *)sipSelf, - cls); - } - else - { - /* - * We don't know what it is so just return and assume that an - * appropriate exception will be raised later on. - */ - Py_INCREF(reimp); - } - } - else - { - /* Use the fast track in future. */ - *pymc = 1; - - if (cname != NULL) - { - /* Note that this will only be raised once per method. */ - PyErr_Format(PyExc_NotImplementedError, - "%s.%s() is abstract and must be overridden", cname, - mname); - PyErr_Print(); - } - -#ifdef WITH_THREAD - PyGILState_Release(*gil); -#endif - } - - return reimp; - -release_gil: -#ifdef WITH_THREAD - PyGILState_Release(*gil); -#endif - return NULL; -} - - -/* - * Convert a C/C++ pointer to the object that wraps it. - */ -static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td) -{ - return (PyObject *)sipOMFindObject(&cppPyMap, cppPtr, td); -} - - -/* - * The default access function. - */ -void *sip_api_get_address(sipSimpleWrapper *w) -{ - return (w->access_func != NULL) ? w->access_func(w, GuardedPointer) : w->data; -} - - -/* - * The access function for handwritten access functions. - */ -static void *explicit_access_func(sipSimpleWrapper *sw, AccessFuncOp op) -{ - typedef void *(*explicitAccessFunc)(void); - - if (op == ReleaseGuard) - return NULL; - - return ((explicitAccessFunc)(sw->data))(); -} - - -/* - * The access function for indirect access. - */ -static void *indirect_access_func(sipSimpleWrapper *sw, AccessFuncOp op) -{ - void *addr; - - switch (op) - { - case UnguardedPointer: - addr = sw->data; - break; - - case GuardedPointer: - addr = *((void **)sw->data); - break; - - default: - addr = NULL; - } - - return addr; -} - - -/* - * Get the C/C++ pointer for a complex object. Note that not casting the C++ - * pointer is a bug. However this would only ever be called by PyQt3 signal - * emitter code and PyQt doesn't contain anything that multiply inherits from - * QObject. - */ -static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw) -{ - return getComplexCppPtr(sw, NULL); -} - - -/* - * Get the C/C++ pointer for a complex object and optionally cast it to the - * required type. - */ -static void *getComplexCppPtr(sipSimpleWrapper *sw, const sipTypeDef *td) -{ - if (!sipIsDerived(sw)) - { - PyErr_SetString(PyExc_RuntimeError, - "no access to protected functions or signals for objects not created from Python"); - - return NULL; - } - - return sip_api_get_cpp_ptr(sw, td); -} - - -/* - * Get the C/C++ pointer from a wrapper and optionally cast it to the required - * type. - */ -void *sip_api_get_cpp_ptr(sipSimpleWrapper *sw, const sipTypeDef *td) -{ - void *ptr = sip_api_get_address(sw); - - if (checkPointer(ptr, sw) < 0) - return NULL; - - if (td != NULL) - { - if (PyObject_TypeCheck((PyObject *)sw, sipTypeAsPyTypeObject(td))) - ptr = cast_cpp_ptr(ptr, Py_TYPE(sw), td); - else - ptr = NULL; - - if (ptr == NULL) - PyErr_Format(PyExc_TypeError, "could not convert '%s' to '%s'", - Py_TYPE(sw)->tp_name, - sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td)); - } - - return ptr; -} - - -/* - * Cast a C/C++ pointer from a source type to a destination type. - */ -static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type, - const sipTypeDef *dst_type) -{ - sipCastFunc cast = ((const sipClassTypeDef *)((sipWrapperType *)src_type)->wt_td)->ctd_cast; - - /* C structures and base classes don't have cast functions. */ - if (cast != NULL) - ptr = (*cast)(ptr, dst_type); - - return ptr; -} - - -/* - * Check that a pointer is non-NULL. - */ -static int checkPointer(void *ptr, sipSimpleWrapper *sw) -{ - if (ptr == NULL) - { - PyErr_Format(PyExc_RuntimeError, (sipWasCreated(sw) ? - "wrapped C/C++ object of type %s has been deleted" : - "super-class __init__() of type %s was never called"), - Py_TYPE(sw)->tp_name); - return -1; - } - - return 0; -} - - -/* - * Keep an extra reference to an object. - */ -static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj) -{ - PyObject *dict, *key_obj; - - /* - * If there isn't a "self" to keep the extra reference for later garbage - * collection then just take a reference and let it leak. - */ - if (self == NULL) - { - Py_XINCREF(obj); - return; - } - - /* Create the extra references dictionary if needed. */ - if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL) - { - if ((dict = PyDict_New()) == NULL) - return; - - ((sipSimpleWrapper *)self)->extra_refs = dict; - } - - if ((key_obj = PyLong_FromLong(key)) != NULL) - { - /* This can happen if the argument was optional. */ - if (obj == NULL) - obj = Py_None; - - PyDict_SetItem(dict, key_obj, obj); - Py_DECREF(key_obj); - } -} - - -/* - * Get an object that has an extra reference. - */ -static PyObject *sip_api_get_reference(PyObject *self, int key) -{ - PyObject *dict, *key_obj, *obj; - - /* Get the extra references dictionary if there is one. */ - if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL) - return NULL; - - if ((key_obj = PyLong_FromLong(key)) == NULL) - return NULL; - - obj = PyDict_GetItem(dict, key_obj); - Py_DECREF(key_obj); - Py_XINCREF(obj); - - return obj; -} - - -/* - * Return TRUE if an object is owned by Python. Note that this isn't - * implemented as a macro in sip.h because the position of the sw_flags field - * is dependent on the version of Python. - */ -static int sip_api_is_owned_by_python(sipSimpleWrapper *sw) -{ - return sipIsPyOwned(sw); -} - - -/* - * Return TRUE if the type of a C++ instance is a derived class. Note that - * this isn't implemented as a macro in sip.h because the position of the - * sw_flags field is dependent on the version of Python. - */ -static int sip_api_is_derived_class(sipSimpleWrapper *sw) -{ - return sipIsDerived(sw); -} - - -/* - * Get the user defined object from a wrapped object. Note that this isn't - * implemented as a macro in sip.h because the position of the user field is - * dependent on the version of Python. - */ -static PyObject *sip_api_get_user_object(const sipSimpleWrapper *sw) -{ - return sw->user; -} - - -/* - * Set the user defined object in a wrapped object. Note that this isn't - * implemented as a macro in sip.h because the position of the user field is - * dependent on the version of Python. - */ -static void sip_api_set_user_object(sipSimpleWrapper *sw, PyObject *user) -{ - sw->user = user; -} - - -/* - * Check to see if a Python object can be converted to a type. - */ -static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td, - int flags) -{ - int ok; - - assert(td == NULL || sipTypeIsClass(td) || sipTypeIsMapped(td)); - - if (td == NULL) - { - /* - * The type must be /External/ and the module that contains the - * implementation hasn't been imported. - */ - ok = FALSE; - } - else if (pyObj == Py_None) - { - /* If the type explicitly handles None then ignore the flags. */ - if (sipTypeAllowNone(td)) - ok = TRUE; - else - ok = ((flags & SIP_NOT_NONE) == 0); - } - else - { - sipConvertToFunc cto; - - if (sipTypeIsClass(td)) - { - cto = ((const sipClassTypeDef *)td)->ctd_cto; - - if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) - ok = PyObject_TypeCheck(pyObj, sipTypeAsPyTypeObject(td)); - else - ok = cto(pyObj, NULL, NULL, NULL); - } - else - { - cto = ((const sipMappedTypeDef *)td)->mtd_cto; - ok = cto(pyObj, NULL, NULL, NULL); - } - } - - return ok; -} - - -/* - * Convert a Python object to a C/C++ pointer, assuming a previous call to - * sip_api_can_convert_to_type() has been successful. Allow ownership to be - * transferred and any type converters to be disabled. - */ -static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp) -{ - void *cpp = NULL; - int state = 0; - - assert(sipTypeIsClass(td) || sipTypeIsMapped(td)); - - /* Don't convert if there has already been an error. */ - if (!*iserrp) - { - /* Do the conversion. */ - if (pyObj == Py_None && !sipTypeAllowNone(td)) - cpp = NULL; - else - { - sipConvertToFunc cto; - - if (sipTypeIsClass(td)) - { - cto = ((const sipClassTypeDef *)td)->ctd_cto; - - if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) - { - if ((cpp = sip_api_get_cpp_ptr((sipSimpleWrapper *)pyObj, td)) == NULL) - *iserrp = TRUE; - else if (transferObj != NULL) - { - if (transferObj == Py_None) - sip_api_transfer_back(pyObj); - else - sip_api_transfer_to(pyObj, transferObj); - } - } - else - { - state = cto(pyObj, &cpp, iserrp, transferObj); - } - } - else - { - cto = ((const sipMappedTypeDef *)td)->mtd_cto; - state = cto(pyObj, &cpp, iserrp, transferObj); - } - } - } - - if (statep != NULL) - *statep = state; - - return cpp; -} - - -/* - * Convert a Python object to a C/C++ pointer and raise an exception if it - * can't be done. - */ -void *sip_api_force_convert_to_type(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp) -{ - /* Don't even try if there has already been an error. */ - if (*iserrp) - return NULL; - - /* See if the object's type can be converted. */ - if (!sip_api_can_convert_to_type(pyObj, td, flags)) - { - if (sipTypeIsMapped(td)) - PyErr_Format(PyExc_TypeError, - "%s cannot be converted to a C/C++ %s in this context", - Py_TYPE(pyObj)->tp_name, sipTypeName(td)); - else - PyErr_Format(PyExc_TypeError, - "%s cannot be converted to %s.%s in this context", - Py_TYPE(pyObj)->tp_name, sipNameOfModule(td->td_module), - sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td)); - - if (statep != NULL) - *statep = 0; - - *iserrp = TRUE; - return NULL; - } - - /* Do the conversion. */ - return sip_api_convert_to_type(pyObj, td, transferObj, flags, statep, - iserrp); -} - - -/* - * Release a possibly temporary C/C++ instance created by a type converter. - */ -static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state) -{ - /* See if there is something to release. */ - if (state & SIP_TEMPORARY) - release(cpp, td, state); -} - - -/* - * Release an instance. - */ -static void release(void *addr, const sipTypeDef *td, int state) -{ - sipReleaseFunc rel; - - if (sipTypeIsClass(td)) - { - rel = ((const sipClassTypeDef *)td)->ctd_release; - - /* - * If there is no release function then it must be a C structure and we - * can just free it. - */ - if (rel == NULL) - sip_api_free(addr); - } - else if (sipTypeIsMapped(td)) - rel = ((const sipMappedTypeDef *)td)->mtd_release; - else - rel = NULL; - - if (rel != NULL) - rel(addr, state); -} - - -/* - * Convert a C/C++ instance to a Python instance. - */ -PyObject *sip_api_convert_from_type(void *cpp, const sipTypeDef *td, - PyObject *transferObj) -{ - PyObject *py; - sipConvertFromFunc cfrom; - - assert(sipTypeIsClass(td) || sipTypeIsMapped(td)); - - /* Handle None. */ - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - cpp = resolve_proxy(td, cpp); - - cfrom = get_from_convertor(td); - - if (cfrom != NULL) - return cfrom(cpp, transferObj); - - /* - * See if we have already wrapped it. Invoking sub-class code can be - * expensive so we check the cache first, even though the sub-class code - * might perform a down-cast. - */ - if ((py = sip_api_get_pyobject(cpp, td)) == NULL && sipTypeHasSCC(td)) - { - void *orig_cpp = cpp; - const sipTypeDef *orig_td = td; - - /* Apply the sub-class converter. */ - td = convertSubClass(td, &cpp); - - /* - * If the sub-class converter has done something then check the cache - * again using the modified values. - */ - if (cpp != orig_cpp || td != orig_td) - py = sip_api_get_pyobject(cpp, td); - } - - if (py != NULL) - Py_INCREF(py); - else if ((py = wrap_simple_instance(cpp, td, NULL, SIP_SHARE_MAP)) == NULL) - return NULL; - - /* Handle any ownership transfer. */ - if (transferObj != NULL) - { - if (transferObj == Py_None) - sip_api_transfer_back(py); - else - sip_api_transfer_to(py, transferObj); - } - - return py; -} - - -/* - * Convert a new C/C++ instance to a Python instance. - */ -static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td, - PyObject *transferObj) -{ - sipWrapper *owner; - sipConvertFromFunc cfrom; - - /* Handle None. */ - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - cpp = resolve_proxy(td, cpp); - - cfrom = get_from_convertor(td); - - if (cfrom != NULL) - { - PyObject *res = cfrom(cpp, transferObj); - - if (res != NULL) - { - /* - * We no longer need the C/C++ instance so we release it (unless - * its ownership is transferred). This means this call is - * semantically equivalent to the case where we are wrapping a - * class. - */ - if (transferObj == NULL || transferObj == Py_None) - release(cpp, td, 0); - } - - return res; - } - - /* Apply any sub-class converter. */ - if (sipTypeHasSCC(td)) - td = convertSubClass(td, &cpp); - - /* Handle any ownership transfer. */ - if (transferObj == NULL || transferObj == Py_None) - owner = NULL; - else - owner = (sipWrapper *)transferObj; - - return wrap_simple_instance(cpp, td, owner, - (owner == NULL ? SIP_PY_OWNED : 0)); -} - - -/* - * Implement the normal transfer policy for the result of %ConvertToTypeCode, - * ie. it is temporary unless it is being transferred from Python. - */ -int sip_api_get_state(PyObject *transferObj) -{ - return (transferObj == NULL || transferObj == Py_None) ? SIP_TEMPORARY : 0; -} - - -/* - * This is set by sip_api_find_type() before calling bsearch() on the types - * table for the module. This is a hack that works around the problem of - * unresolved externally defined types. - */ -static sipExportedModuleDef *module_searched; - - -/* - * The bsearch() helper function for searching the types table. - */ -static int compareTypeDef(const void *key, const void *el) -{ - const char *s1 = (const char *)key; - const char *s2 = NULL; - const sipTypeDef *td; - char ch1, ch2; - - /* Allow for unresolved externally defined types. */ - td = *(const sipTypeDef **)el; - - if (td != NULL) - { - s2 = sipTypeName(td); - } - else - { - sipExternalTypeDef *etd = module_searched->em_external; - - assert(etd != NULL); - - /* Find which external type it is. */ - while (etd->et_nr >= 0) - { - const void *tdp = &module_searched->em_types[etd->et_nr]; - - if (tdp == el) - { - s2 = etd->et_name; - break; - } - - ++etd; - } - - assert(s2 != NULL); - } - - /* - * Compare while ignoring spaces so that we don't impose a rigorous naming - * standard. This only really affects template-based mapped types. - */ - do - { - while ((ch1 = *s1++) == ' ') - ; - - while ((ch2 = *s2++) == ' ') - ; - - /* We might be looking for a pointer or a reference. */ - if ((ch1 == '*' || ch1 == '&' || ch1 == '\0') && ch2 == '\0') - return 0; - } - while (ch1 == ch2); - - return (ch1 < ch2 ? -1 : 1); -} - - -/* - * Return the type structure for a particular type. - */ -static const sipTypeDef *sip_api_find_type(const char *type) -{ - sipExportedModuleDef *em; - - for (em = moduleList; em != NULL; em = em->em_next) - { - sipTypeDef **tdp; - - /* The backdoor to the comparison helper. */ - module_searched = em; - - tdp = (sipTypeDef **)bsearch((const void *)type, - (const void *)em->em_types, em->em_nrtypes, - sizeof (sipTypeDef *), compareTypeDef); - - if (tdp != NULL) - { - /* - * Note that this will be NULL for unresolved externally defined - * types. - */ - return *tdp; - } - } - - return NULL; -} - - -/* - * Return the mapped type structure for a particular mapped type. This is - * deprecated. - */ -static const sipMappedType *sip_api_find_mapped_type(const char *type) -{ - /* Remove in v5.1. */ - - const sipTypeDef *td = sip_api_find_type(type); - - if (td != NULL && sipTypeIsMapped(td)) - return (const sipMappedType *)td; - - return NULL; -} - - -/* - * Return the type structure for a particular class. This is deprecated. - */ -static sipWrapperType *sip_api_find_class(const char *type) -{ - /* Remove in v5.1. */ - - const sipTypeDef *td = sip_api_find_type(type); - - if (td != NULL && sipTypeIsClass(td)) - return (sipWrapperType *)sipTypeAsPyTypeObject(td); - - return NULL; -} - - -/* - * Return the type structure for a particular named unscoped enum. This is - * deprecated. - */ -static PyTypeObject *sip_api_find_named_enum(const char *type) -{ - /* Remove in v5.1. */ - - const sipTypeDef *td = sip_api_find_type(type); - - if (td != NULL && sipTypeIsEnum(td)) - return sipTypeAsPyTypeObject(td); - - return NULL; -} - - -/* - * Save the components of a Python method. - */ -void sipSaveMethod(sipPyMethod *pm, PyObject *meth) -{ - pm->mfunc = PyMethod_GET_FUNCTION(meth); - pm->mself = PyMethod_GET_SELF(meth); -} - - -/* - * Call a hook. - */ -static void sip_api_call_hook(const char *hookname) -{ - PyObject *dictofmods, *mod, *dict, *hook, *res; - - /* Get the dictionary of modules. */ - if ((dictofmods = PyImport_GetModuleDict()) == NULL) - return; - - /* Get the builtins module. */ - if ((mod = PyDict_GetItemString(dictofmods, "builtins")) == NULL) - return; - - /* Get it's dictionary. */ - if ((dict = PyModule_GetDict(mod)) == NULL) - return; - - /* Get the function hook. */ - if ((hook = PyDict_GetItemString(dict, hookname)) == NULL) - return; - - /* Call the hook and discard any result. */ - res = PyObject_Call(hook, empty_tuple, NULL); - - Py_XDECREF(res); -} - - -/* - * Call any sub-class converters for a given type returning a pointer to the - * sub-type object, and possibly modifying the C++ address (in the case of - * multiple inheritance). - */ -static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) -{ - /* Handle the trivial case. */ - if (*cppPtr == NULL) - return NULL; - - /* Try the conversions until told to stop. */ - while (convertPass(&td, cppPtr)) - ; - - return td; -} - - -/* - * Do a single pass through the available converters. - */ -static int convertPass(const sipTypeDef **tdp, void **cppPtr) -{ - PyTypeObject *py_type = sipTypeAsPyTypeObject(*tdp); - sipExportedModuleDef *em; - - /* - * Note that this code depends on the fact that a module appears in the - * list of modules before any module it imports, ie. sub-class converters - * will be invoked for more specific types first. - */ - for (em = moduleList; em != NULL; em = em->em_next) - { - sipSubClassConvertorDef *scc; - - if ((scc = em->em_convertors) == NULL) - continue; - - while (scc->scc_convertor != NULL) - { - PyTypeObject *base_type = sipTypeAsPyTypeObject(scc->scc_basetype); - - /* - * The base type is the "root" class that may have a number of - * converters each handling a "branch" of the derived tree of - * classes. The "root" normally implements the base function that - * provides the RTTI used by the converters and is re-implemented - * by derived classes. We therefore see if the target type is a - * sub-class of the root, ie. see if the converter might be able to - * convert the target type to something more specific. - */ - if (PyType_IsSubtype(py_type, base_type)) - { - void *ptr; - const sipTypeDef *sub_td; - - ptr = cast_cpp_ptr(*cppPtr, py_type, scc->scc_basetype); - - if ((sub_td = (*scc->scc_convertor)(&ptr)) != NULL) - { - PyTypeObject *sub_type = sipTypeAsPyTypeObject(sub_td); - - /* - * We are only interested in types that are not - * super-classes of the target. This happens either - * because it is in an earlier converter than the one that - * handles the type or it is in a later converter that - * handles a different branch of the hierarchy. Either - * way, the ordering of the modules ensures that there will - * be no more than one and that it will be the right one. - */ - if (!PyType_IsSubtype(py_type, sub_type)) - { - *tdp = sub_td; - *cppPtr = ptr; - - /* - * Finally we allow the converter to return a type that - * is apparently unrelated to the current converter. - * This causes the whole process to be restarted with - * the new values. The use case is PyQt's QLayoutItem. - */ - return !PyType_IsSubtype(sub_type, base_type); - } - } - } - - ++scc; - } - } - - /* - * We haven't found the exact type, so return the most specific type that - * it must be. This can happen legitimately if the wrapped library is - * returning an internal class that is down-cast to a more generic class. - * Also we want this function to be safe when a class doesn't have any - * converters. - */ - return FALSE; -} - - -/* - * The bsearch() helper function for searching a sorted string map table. - */ -static int compareStringMapEntry(const void *key,const void *el) -{ - return strcmp((const char *)key,((const sipStringTypeClassMap *)el)->typeString); -} - - -/* - * A convenience function for %ConvertToSubClassCode for types represented as a - * string. Returns the Python class object or NULL if the type wasn't - * recognised. This is deprecated. - */ -static sipWrapperType *sip_api_map_string_to_class(const char *typeString, - const sipStringTypeClassMap *map, int maplen) -{ - /* Remove in v5.1. */ - - sipStringTypeClassMap *me; - - me = (sipStringTypeClassMap *)bsearch((const void *)typeString, - (const void *)map,maplen, - sizeof (sipStringTypeClassMap), - compareStringMapEntry); - - return ((me != NULL) ? *me->pyType : NULL); -} - - -/* - * The bsearch() helper function for searching a sorted integer map table. - */ -static int compareIntMapEntry(const void *keyp,const void *el) -{ - int key = *(int *)keyp; - - if (key > ((const sipIntTypeClassMap *)el)->typeInt) - return 1; - - if (key < ((const sipIntTypeClassMap *)el)->typeInt) - return -1; - - return 0; -} - - -/* - * A convenience function for %ConvertToSubClassCode for types represented as - * an integer. Returns the Python class object or NULL if the type wasn't - * recognised. This is deprecated. - */ -static sipWrapperType *sip_api_map_int_to_class(int typeInt, - const sipIntTypeClassMap *map, int maplen) -{ - /* Remove in v5.1. */ - - sipIntTypeClassMap *me; - - me = (sipIntTypeClassMap *)bsearch((const void *)&typeInt, - (const void *)map,maplen, - sizeof (sipIntTypeClassMap), - compareIntMapEntry); - - return ((me != NULL) ? *me->pyType : NULL); -} - - -/* - * Raise an unknown exception. Make no assumptions about the GIL. - */ -static void sip_api_raise_unknown_exception(void) -{ - static PyObject *mobj = NULL; - - SIP_BLOCK_THREADS - - objectify("unknown", &mobj); - - PyErr_SetObject(PyExc_Exception, mobj); - - SIP_UNBLOCK_THREADS -} - - -/* - * Raise an exception implemented as a type. Make no assumptions about the - * GIL. - */ -static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr) -{ - PyObject *self; - - assert(sipTypeIsClass(td)); - - SIP_BLOCK_THREADS - - self = wrap_simple_instance(ptr, td, NULL, SIP_PY_OWNED); - - PyErr_SetObject((PyObject *)sipTypeAsPyTypeObject(td), self); - - Py_XDECREF(self); - - SIP_UNBLOCK_THREADS -} - - -/* - * Return the generated type structure of an encoded type. - */ -static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, - sipExportedModuleDef *em) -{ - if (enc->sc_module == 255) - return em->em_types[enc->sc_type]; - - return em->em_imports[enc->sc_module].im_imported_types[enc->sc_type].it_td; -} - - -/* - * Return the generated class type structure of a class's super-class. - */ -sipClassTypeDef *sipGetGeneratedClassType(const sipEncodedTypeDef *enc, - const sipClassTypeDef *ctd) -{ - return (sipClassTypeDef *)getGeneratedType(enc, ctd->ctd_base.td_module); -} - - -/* - * Find a particular slot function for a type. - */ -static void *findSlot(PyObject *self, sipPySlotType st) -{ - void *slot; - PyTypeObject *py_type = Py_TYPE(self); - - /* See if it is a wrapper. */ - if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type)) - { - const sipClassTypeDef *ctd; - - ctd = (sipClassTypeDef *)((sipWrapperType *)(py_type))->wt_td; - - slot = findSlotInClass(ctd, st); - } - else - { - sipEnumTypeDef *etd; - - /* If it is not a wrapper then it must be an enum. */ - assert(PyObject_TypeCheck((PyObject *)py_type, &sipEnumType_Type)); - - etd = (sipEnumTypeDef *)((sipEnumTypeObject *)(py_type))->type; - - assert(etd->etd_pyslots != NULL); - - slot = findSlotInSlotList(etd->etd_pyslots, st); - } - - return slot; -} - - -/* - * Find a particular slot function in a class hierarchy. - */ -static void *findSlotInClass(const sipClassTypeDef *ctd, sipPySlotType st) -{ - void *slot; - - if (ctd->ctd_pyslots != NULL) - slot = findSlotInSlotList(ctd->ctd_pyslots, st); - else - slot = NULL; - - if (slot == NULL) - { - sipEncodedTypeDef *sup; - - /* Search any super-types. */ - if ((sup = ctd->ctd_supers) != NULL) - { - do - { - const sipClassTypeDef *sup_ctd = sipGetGeneratedClassType( - sup, ctd); - - slot = findSlotInClass(sup_ctd, st); - } - while (slot == NULL && !sup++->sc_flag); - } - } - - return slot; -} - - -/* - * Find a particular slot function in a particular type. - */ -static void *findSlotInSlotList(sipPySlotDef *psd, sipPySlotType st) -{ - while (psd->psd_func != NULL) - { - if (psd->psd_type == st) - return psd->psd_func; - - ++psd; - } - - return NULL; -} - - -/* - * Return the C/C++ address and the generated class structure for a wrapper. - */ -static void *getPtrTypeDef(sipSimpleWrapper *self, const sipClassTypeDef **ctd) -{ - *ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(self))->wt_td; - - return (sipNotInMap(self) ? NULL : sip_api_get_address(self)); -} - - -/* - * Handle an objobjargproc slot. - */ -static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2, - sipPySlotType st) -{ - int (*f)(PyObject *, PyObject *); - int res; - - f = (int (*)(PyObject *, PyObject *))findSlot(self, st); - - if (f != NULL) - { - PyObject *args; - - /* - * Slot handlers require a single PyObject *. The second argument is - * optional. - */ - if (arg2 == NULL) - { - args = arg1; - Py_INCREF(args); - } - else if ((args = PyTuple_Pack(2, arg1, arg2)) == NULL) - { - return -1; - } - - res = f(self, args); - Py_DECREF(args); - } - else - { - PyErr_SetNone(PyExc_NotImplementedError); - res = -1; - } - - return res; -} - - -/* - * Handle an ssizeobjargproc slot. - */ -static int ssizeobjargprocSlot(PyObject *self, Py_ssize_t arg1, - PyObject *arg2, sipPySlotType st) -{ - int (*f)(PyObject *, PyObject *); - int res; - - f = (int (*)(PyObject *, PyObject *))findSlot(self, st); - - if (f != NULL) - { - PyObject *args; - - /* - * Slot handlers require a single PyObject *. The second argument is - * optional. - */ - if (arg2 == NULL) - args = PyLong_FromSsize_t(arg1); - else - args = Py_BuildValue("(nO)", arg1, arg2); - - if (args == NULL) - return -1; - - res = f(self, args); - Py_DECREF(args); - } - else - { - PyErr_SetNone(PyExc_NotImplementedError); - res = -1; - } - - return res; -} - - -/* - * The metatype alloc slot. - */ -static PyObject *sipWrapperType_alloc(PyTypeObject *self, Py_ssize_t nitems) -{ - PyObject *o; - - /* Call the standard super-metatype alloc. */ - if ((o = PyType_Type.tp_alloc(self, nitems)) == NULL) - return NULL; - - /* - * Consume any extra type specific information and use it to initialise the - * slots. This only happens for directly wrapped classes (and not - * programmer written sub-classes). This must be done in the alloc - * function because it is the only place we can break out of the default - * new() function before PyType_Ready() is called. - */ - if (currentType != NULL) - { - assert(!sipTypeIsEnum(currentType)); - - ((sipWrapperType *)o)->wt_td = currentType; - - if (sipTypeIsClass(currentType)) - { - const sipClassTypeDef *ctd = (const sipClassTypeDef *)currentType; - const char *docstring = ctd->ctd_docstring; - - /* - * Skip the marker that identifies the docstring as being - * automatically generated. - */ - if (docstring != NULL && *docstring == AUTO_DOCSTRING) - ++docstring; - - ((PyTypeObject *)o)->tp_doc = docstring; - - addClassSlots((sipWrapperType *)o, ctd); - - /* Patch any mixin initialiser. */ - if (ctd->ctd_init_mixin != NULL) - ((PyTypeObject *)o)->tp_init = ctd->ctd_init_mixin; - } - } - - return o; -} - - -/* - * The metatype init slot. - */ -static int sipWrapperType_init(sipWrapperType *self, PyObject *args, - PyObject *kwds) -{ - /* Call the standard super-metatype init. */ - if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) - return -1; - - /* - * If we don't yet have any extra type specific information (because we are - * a programmer defined sub-class) then get it from the (first) super-type. - */ - if (self->wt_td == NULL) - { - PyTypeObject *base = ((PyTypeObject *)self)->tp_base; - - self->wt_user_type = TRUE; - - /* - * We allow the class to use this as a meta-type without being derived - * from a class that uses it. This allows mixin classes that need - * their own meta-type to work so long as their meta-type is derived - * from this meta-type. This condition is indicated by the pointer to - * the generated type structure being NULL. - */ - if (base != NULL && PyObject_TypeCheck((PyObject *)base, (PyTypeObject *)&sipWrapperType_Type)) - { - /* TODO: Deprecate this mechanism in favour of an event handler. */ - sipNewUserTypeFunc new_user_type_handler; - - self->wt_td = ((sipWrapperType *)base)->wt_td; - - if (self->wt_td != NULL) - { - /* Call any new type handler. */ - new_user_type_handler = find_new_user_type_handler( - (sipWrapperType *)sipTypeAsPyTypeObject(self->wt_td)); - - if (new_user_type_handler != NULL) - if (new_user_type_handler(self) < 0) - return -1; - } - } - } - else - { - /* - * We must be a generated type so remember the type object in the - * generated type structure. - */ - assert(self->wt_td->td_py_type == NULL); - - self->wt_td->td_py_type = (PyTypeObject *)self; - } - - return 0; -} - - -/* - * The metatype getattro slot. - */ -static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name) -{ - if (add_all_lazy_attrs(((sipWrapperType *)self)->wt_td) < 0) - return NULL; - - return PyType_Type.tp_getattro(self, name); -} - - -/* - * The metatype setattro slot. - */ -static int sipWrapperType_setattro(PyObject *self, PyObject *name, - PyObject *value) -{ - if (add_all_lazy_attrs(((sipWrapperType *)self)->wt_td) < 0) - return -1; - - return PyType_Type.tp_setattro(self, name, value); -} - - -/* - * The instance new slot. - */ -static PyObject *sipSimpleWrapper_new(sipWrapperType *wt, PyObject *args, - PyObject *kwds) -{ - sipTypeDef *td = wt->wt_td; - - (void)args; - (void)kwds; - - /* Check the base types are not being used directly. */ - if (wt == &sipSimpleWrapper_Type || wt == &sipWrapper_Type) - { - PyErr_Format(PyExc_TypeError, - "the %s type cannot be instantiated or sub-classed", - ((PyTypeObject *)wt)->tp_name); - - return NULL; - } - - if (add_all_lazy_attrs(td) < 0) - return NULL; - - /* See if it is a mapped type. */ - if (sipTypeIsMapped(td)) - { - PyErr_Format(PyExc_TypeError, - "%s.%s represents a mapped type and cannot be instantiated", - sipNameOfModule(td->td_module), - sipPyNameOfContainer(get_container(td), td)); - - return NULL; - } - - /* See if it is a namespace. */ - if (sipTypeIsNamespace(td)) - { - PyErr_Format(PyExc_TypeError, - "%s.%s represents a C++ namespace and cannot be instantiated", - sipNameOfModule(td->td_module), - sipPyNameOfContainer(get_container(td), td)); - - return NULL; - } - - /* - * See if the object is being created explicitly rather than being wrapped. - */ - if (!sipIsPending()) - { - /* - * See if it cannot be instantiated or sub-classed from Python, eg. - * it's an opaque class. Some restrictions might be overcome with - * better SIP support. - */ - if (((sipClassTypeDef *)td)->ctd_init == NULL) - { - PyErr_Format(PyExc_TypeError, - "%s.%s cannot be instantiated or sub-classed", - sipNameOfModule(td->td_module), - sipPyNameOfContainer(get_container(td), td)); - - return NULL; - } - - /* See if it is an abstract type. */ - if (sipTypeIsAbstract(td) && !wt->wt_user_type && ((sipClassTypeDef *)td)->ctd_init_mixin == NULL) - { - PyErr_Format(PyExc_TypeError, - "%s.%s represents a C++ abstract class and cannot be instantiated", - sipNameOfModule(td->td_module), - sipPyNameOfContainer(get_container(td), td)); - - return NULL; - } - } - - /* Call the standard super-type new. */ - return PyBaseObject_Type.tp_new((PyTypeObject *)wt, empty_tuple, NULL); -} - - -/* - * The instance init slot. - */ -static int sipSimpleWrapper_init(sipSimpleWrapper *self, PyObject *args, - PyObject *kwds) -{ - void *sipNew; - int sipFlags, from_cpp = TRUE; - sipWrapper *owner; - sipWrapperType *wt = (sipWrapperType *)Py_TYPE(self); - sipTypeDef *td = wt->wt_td; - sipClassTypeDef *ctd = (sipClassTypeDef *)td; - PyObject *unused = NULL; - sipFinalFunc final_func = find_finalisation(ctd); - - /* Check for an existing C++ instance waiting to be wrapped. */ - if (sipGetPending(&sipNew, &owner, &sipFlags) < 0) - return -1; - - if (sipNew == NULL) - { - PyObject *parseErr = NULL, **unused_p = NULL; - - /* See if we are interested in any unused keyword arguments. */ - if (sipTypeCallSuperInit(&ctd->ctd_base) || final_func != NULL || kw_handler != NULL) - unused_p = &unused; - - /* Call the C++ ctor. */ - owner = NULL; - - sipNew = ctd->ctd_init(self, args, kwds, unused_p, (PyObject **)&owner, - &parseErr); - - if (sipNew != NULL) - { - sipFlags = SIP_DERIVED_CLASS; - } - else if (parseErr == NULL) - { - /* - * The C++ ctor must have raised an exception which has been - * translated to a Python exception. - */ - return -1; - } - else - { - sipInitExtenderDef *ie = wt->wt_iextend; - - /* - * If we have not found an appropriate overload then try any - * extenders. - */ - while (PyList_Check(parseErr) && ie != NULL) - { - sipNew = ie->ie_extender(self, args, kwds, &unused, - (PyObject **)&owner, &parseErr); - - if (sipNew != NULL) - break; - - ie = ie->ie_next; - } - - if (sipNew == NULL) - { - const char *docstring = ctd->ctd_docstring; - - /* - * Use the docstring for errors if it was automatically - * generated. - */ - if (docstring != NULL) - { - if (*docstring == AUTO_DOCSTRING) - ++docstring; - else - docstring = NULL; - } - - sip_api_no_function(parseErr, - sipPyNameOfContainer(&ctd->ctd_container, td), - docstring); - - return -1; - } - - sipFlags = 0; - } - - if (owner == NULL) - sipFlags |= SIP_PY_OWNED; - else if ((PyObject *)owner == Py_None) - { - /* This is the hack that means that C++ owns the new instance. */ - sipFlags |= SIP_CPP_HAS_REF; - Py_INCREF(self); - owner = NULL; - } - - /* The instance was created from Python. */ - from_cpp = FALSE; - } - - /* Handler any owner if the type supports the concept. */ - if (PyObject_TypeCheck((PyObject *)self, (PyTypeObject *)&sipWrapper_Type)) - { - /* - * The application may be doing something very unadvisable (like - * calling __init__() for a second time), so make sure we don't already - * have a parent. - */ - removeFromParent((sipWrapper *)self); - - if (owner != NULL) - { - assert(PyObject_TypeCheck((PyObject *)owner, (PyTypeObject *)&sipWrapper_Type)); - - addToParent((sipWrapper *)self, (sipWrapper *)owner); - } - } - - self->data = sipNew; - self->sw_flags = sipFlags | SIP_CREATED; - - /* Set the access function. */ - if (sipIsAccessFunc(self)) - self->access_func = explicit_access_func; - else if (sipIsIndirect(self)) - self->access_func = indirect_access_func; - else - self->access_func = NULL; - - if (!sipNotInMap(self)) - sipOMAddObject(&cppPyMap, self); - - /* If we are wrapping an instance returned from C/C++ then we are done. */ - if (from_cpp) - { - /* - * Invoke any event handlers for instances that are accessed directly. - */ - if (self->access_func == NULL) - { - sipEventHandler *eh; - - for (eh = event_handlers[sipEventWrappedInstance]; eh != NULL; eh = eh->next) - { - if (is_subtype(ctd, eh->ctd)) - { - sipWrappedInstanceEventHandler handler = (sipWrappedInstanceEventHandler)eh->handler; - - handler(sipNew); - } - } - } - - return 0; - } - - /* Call any finalisation code. */ - if (final_func != NULL) - { - PyObject *new_unused = NULL, **new_unused_p; - - if (unused == NULL || unused != kwds) - { - /* - * There are no unused arguments or we have already created a dict - * containing the unused sub-set, so there is no need to create - * another. - */ - new_unused_p = NULL; - } - else - { - /* - * All of the keyword arguments are unused, so if some of them are - * now going to be used then a new dict will be needed. - */ - new_unused_p = &new_unused; - } - - if (final_func((PyObject *)self, sipNew, unused, new_unused_p) < 0) - { - Py_XDECREF(unused); - return -1; - } - - if (new_unused != NULL) - { - Py_DECREF(unused); - unused = new_unused; - } - } - - /* Call the handler if we have one. Remove this in SIP v5. */ - if (kw_handler != NULL && unused != NULL && isQObject((PyObject *)self)) - { - int rc = kw_handler((PyObject *)self, sipNew, unused); - - /* - * A handler will always consume all unused keyword arguments (or raise - * an exception) so discard the dict now. - */ - Py_DECREF(unused); - - if (rc < 0) - return -1; - - unused = NULL; - } - - /* See if we should call the equivalent of super().__init__(). */ - if (sipTypeCallSuperInit(&ctd->ctd_base)) - { - PyObject *next; - - /* Find the next type in the MRO. */ - next = next_in_mro((PyObject *)self, - (PyObject *)&sipSimpleWrapper_Type); - - /* - * If the next type in the MRO is object then take a shortcut by not - * calling super().__init__() but emulating object.__init__() instead. - * This will be the most common case and also allows us to generate a - * better exception message if there are unused keyword arguments. The - * disadvantage is that the exception message will be different if - * there is a mixin. - */ - if (next != (PyObject *)&PyBaseObject_Type) - { - int rc = super_init((PyObject *)self, empty_tuple, unused, next); - - Py_XDECREF(unused); - - return rc; - } - } - - if (unused_backdoor != NULL) - { - /* - * We are being called by a mixin's __init__ so save any unused - * arguments for it to pass on to the main class's __init__. - */ - *unused_backdoor = unused; - } - else if (unused != NULL) - { - /* We shouldn't have any unused keyword arguments. */ - if (PyDict_Size(unused) != 0) - { - PyObject *key, *value; - Py_ssize_t pos = 0; - - /* Just report one of the unused arguments. */ - PyDict_Next(unused, &pos, &key, &value); - - PyErr_Format(PyExc_TypeError, - "'%S' is an unknown keyword argument", key); - - Py_DECREF(unused); - - return -1; - } - - Py_DECREF(unused); - } - - return 0; -} - - -/* - * Get the C++ address of a mixin. - */ -static void *sip_api_get_mixin_address(sipSimpleWrapper *w, - const sipTypeDef *td) -{ - PyObject *mixin; - void *cpp; - - if ((mixin = PyObject_GetAttrString((PyObject *)w, sipTypeName(td))) == NULL) - { - PyErr_Clear(); - return NULL; - } - - cpp = sip_api_get_address((sipSimpleWrapper *)mixin); - - Py_DECREF(mixin); - - return cpp; -} - - -/* - * Initialise a mixin. - */ -static int sip_api_init_mixin(PyObject *self, PyObject *args, PyObject *kwds, - const sipClassTypeDef *ctd) -{ - int rc; - Py_ssize_t pos; - PyObject *unused, *mixin, *mixin_name, *key, *value; - PyTypeObject *self_wt = sipTypeAsPyTypeObject(((sipWrapperType *)Py_TYPE(self))->wt_td); - PyTypeObject *wt = sipTypeAsPyTypeObject(&ctd->ctd_base); - - static PyObject *double_us = NULL; - - if (objectify("__", &double_us) < 0) - return -1; - - /* If we are not a mixin to another wrapped class then behave as normal. */ - if (PyType_IsSubtype(self_wt, wt)) - return super_init(self, args, kwds, next_in_mro(self, (PyObject *)wt)); - - /* - * Create the mixin instance. Retain the positional arguments for the - * super-class. Remember that, even though the mixin appears after the - * main class in the MRO, it appears before sipWrapperType where the main - * class's arguments are actually parsed. - */ - unused = NULL; - unused_backdoor = &unused; - mixin = PyObject_Call((PyObject *)wt, empty_tuple, kwds); - unused_backdoor = NULL; - - if (mixin == NULL) - goto gc_unused; - - /* Make sure the mixin can find the main instance. */ - ((sipSimpleWrapper *)mixin)->mixin_main = self; - Py_INCREF(self); - - if ((mixin_name = PyUnicode_FromString(sipTypeName(&ctd->ctd_base))) == NULL) - { - Py_DECREF(mixin); - goto gc_unused; - } - - rc = PyObject_SetAttr(self, mixin_name, mixin); - Py_DECREF(mixin); - - if (rc < 0) - goto gc_mixin_name; - - /* Add the mixin's useful attributes to the main class. */ - pos = 0; - - while (PyDict_Next(wt->tp_dict, &pos, &key, &value)) - { - /* Don't replace existing values. */ - if (PyDict_Contains(Py_TYPE(self)->tp_dict, key) != 0) - continue; - - /* Skip values with names that start with double underscore. */ - if (!PyUnicode_Check(key)) - continue; - - /* - * Despite what the docs say this returns a Py_ssize_t - although the - * docs are probably right. - */ - rc = (int)PyUnicode_Tailmatch(key, double_us, 0, 2, -1); - - if (rc < 0) - goto gc_mixin_name; - - if (rc > 0) - continue; - - if (PyObject_IsInstance(value, (PyObject *)&sipMethodDescr_Type)) - { - if ((value = sipMethodDescr_Copy(value, mixin_name)) == NULL) - goto gc_mixin_name; - } - else if (PyObject_IsInstance(value, (PyObject *)&sipVariableDescr_Type)) - { - if ((value = sipVariableDescr_Copy(value, mixin_name)) == NULL) - goto gc_mixin_name; - } - else - { - Py_INCREF(value); - } - - rc = PyDict_SetItem(Py_TYPE(self)->tp_dict, key, value); - - Py_DECREF(value); - - if (rc < 0) - goto gc_mixin_name; - } - - Py_DECREF(mixin_name); - - /* Call the super-class's __init__ with any remaining arguments. */ - rc = super_init(self, args, unused, next_in_mro(self, (PyObject *)wt)); - Py_XDECREF(unused); - - return rc; - -gc_mixin_name: - Py_DECREF(mixin_name); - -gc_unused: - Py_XDECREF(unused); - - return -1; -} - - -/* - * Return the next in the MRO of an instance after a given type. - */ -static PyObject *next_in_mro(PyObject *self, PyObject *after) -{ - Py_ssize_t i; - PyObject *mro; - - mro = Py_TYPE(self)->tp_mro; - assert(PyTuple_Check(mro)); - - for (i = 0; i < PyTuple_GET_SIZE(mro); ++i) - if (PyTuple_GET_ITEM(mro, i) == after) - break; - - /* Assert that we have found ourself and that we are not the last. */ - assert(i + 1 < PyTuple_GET_SIZE(mro)); - - return PyTuple_GET_ITEM(mro, i + 1); -} - - -/* - * Call the equivalent of super()__init__() of an instance. - */ -static int super_init(PyObject *self, PyObject *args, PyObject *kwds, - PyObject *type) -{ - int i; - PyObject *init, *init_args, *init_res; - - if ((init = PyObject_GetAttr(type, init_name)) == NULL) - return -1; - - if ((init_args = PyTuple_New(1 + PyTuple_GET_SIZE(args))) == NULL) - { - Py_DECREF(init); - return -1; - } - - PyTuple_SET_ITEM(init_args, 0, self); - Py_INCREF(self); - - for (i = 0; i < PyTuple_GET_SIZE(args); ++i) - { - PyObject *arg = PyTuple_GET_ITEM(args, i); - - PyTuple_SET_ITEM(init_args, 1 + i, arg); - Py_INCREF(arg); - } - - init_res = PyObject_Call(init, init_args, kwds); - Py_DECREF(init_args); - Py_DECREF(init); - Py_XDECREF(init_res); - - return (init_res != NULL) ? 0 : -1; -} - - -/* - * Find any finalisation function for a class, searching its super-classes if - * necessary. - */ -static sipFinalFunc find_finalisation(sipClassTypeDef *ctd) -{ - sipEncodedTypeDef *sup; - - if (ctd->ctd_final != NULL) - return ctd->ctd_final; - - if ((sup = ctd->ctd_supers) != NULL) - do - { - sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); - sipFinalFunc func; - - if ((func = find_finalisation(sup_ctd)) != NULL) - return func; - } - while (!sup++->sc_flag); - - return NULL; -} - - -/* - * Find any new user type handler function for a class, searching its - * super-classes if necessary. - */ -static sipNewUserTypeFunc find_new_user_type_handler(sipWrapperType *wt) -{ - sipEncodedTypeDef *sup; - sipClassTypeDef *ctd; - - if (wt->wt_new_user_type_handler != NULL) - return wt->wt_new_user_type_handler; - - ctd = (sipClassTypeDef *)wt->wt_td; - - if ((sup = ctd->ctd_supers) != NULL) - { - do - { - sipTypeDef *sup_td = getGeneratedType(sup, ctd->ctd_base.td_module); - sipNewUserTypeFunc func; - - wt = (sipWrapperType *)sipTypeAsPyTypeObject(sup_td); - - if ((func = find_new_user_type_handler(wt)) != NULL) - return func; - } - while (!sup++->sc_flag); - } - - return NULL; -} - - -/* - * The instance traverse slot. - */ -static int sipSimpleWrapper_traverse(sipSimpleWrapper *self, visitproc visit, - void *arg) -{ - int vret; - void *ptr; - const sipClassTypeDef *ctd; - - /* Call any handwritten traverse code. */ - if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) - if (ctd->ctd_traverse != NULL) - if ((vret = ctd->ctd_traverse(ptr, visit, arg)) != 0) - return vret; - - if (self->dict != NULL) - if ((vret = visit(self->dict, arg)) != 0) - return vret; - - if (self->extra_refs != NULL) - if ((vret = visit(self->extra_refs, arg)) != 0) - return vret; - - if (self->user != NULL) - if ((vret = visit(self->user, arg)) != 0) - return vret; - - if (self->mixin_main != NULL) - if ((vret = visit(self->mixin_main, arg)) != 0) - return vret; - - return 0; -} - - -/* - * The instance clear slot. - */ -static int sipSimpleWrapper_clear(sipSimpleWrapper *self) -{ - int vret = 0; - void *ptr; - const sipClassTypeDef *ctd; - PyObject *tmp; - - /* Call any handwritten clear code. */ - if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) - if (ctd->ctd_clear != NULL) - vret = ctd->ctd_clear(ptr); - - /* Remove the instance dictionary. */ - tmp = self->dict; - self->dict = NULL; - Py_XDECREF(tmp); - - /* Remove any extra references dictionary. */ - tmp = self->extra_refs; - self->extra_refs = NULL; - Py_XDECREF(tmp); - - /* Remove any user object. */ - tmp = self->user; - self->user = NULL; - Py_XDECREF(tmp); - - /* Remove any mixin main. */ - tmp = self->mixin_main; - self->mixin_main = NULL; - Py_XDECREF(tmp); - - return vret; -} - - -/* - * The instance get buffer slot. - */ -static int sipSimpleWrapper_getbuffer(sipSimpleWrapper *self, Py_buffer *buf, - int flags) -{ - void *ptr; - const sipClassTypeDef *ctd; - - if ((ptr = getPtrTypeDef(self, &ctd)) == NULL) - return -1; - - if (sipTypeUseLimitedAPI(&ctd->ctd_base)) - { - sipGetBufferFuncLimited getbuffer = (sipGetBufferFuncLimited)ctd->ctd_getbuffer; - sipBufferDef bd; - - /* - * Ensure all fields have a default value. This means that extra - * fields can be appended in the future that older handwritten code - * doesn't know about. - */ - memset(&bd, 0, sizeof(sipBufferDef)); - - if (getbuffer((PyObject *)self, ptr, &bd) < 0) - return -1; - - return PyBuffer_FillInfo(buf, (PyObject *)self, bd.bd_buffer, - bd.bd_length, bd.bd_readonly, flags); - } - - return ctd->ctd_getbuffer((PyObject *)self, ptr, buf, flags); -} - - -/* - * The instance release buffer slot. - */ -static void sipSimpleWrapper_releasebuffer(sipSimpleWrapper *self, - Py_buffer *buf) -{ - void *ptr; - const sipClassTypeDef *ctd; - - if ((ptr = getPtrTypeDef(self, &ctd)) == NULL) - return; - - if (sipTypeUseLimitedAPI(&ctd->ctd_base)) - { - sipReleaseBufferFuncLimited releasebuffer = (sipReleaseBufferFuncLimited)ctd->ctd_releasebuffer; - - releasebuffer((PyObject *)self, ptr); - - return; - } - - ctd->ctd_releasebuffer((PyObject *)self, ptr, buf); -} - - -/* - * The instance dealloc slot. - */ -static void sipSimpleWrapper_dealloc(sipSimpleWrapper *self) -{ - PyObject *error_type, *error_value, *error_traceback; - - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - forgetObject(self); - - /* - * Now that the C++ object no longer exists we can tidy up the Python - * object. We used to do this first but that meant lambda slots were - * removed too soon (if they were connected to QObject.destroyed()). - */ - sipSimpleWrapper_clear(self); - - /* Call the standard super-type dealloc. */ - PyBaseObject_Type.tp_dealloc((PyObject *)self); - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); -} - - -/* - * The type call slot. - */ -static PyObject *slot_call(PyObject *self, PyObject *args, PyObject *kw) -{ - PyObject *(*f)(PyObject *, PyObject *, PyObject *); - - f = (PyObject *(*)(PyObject *, PyObject *, PyObject *))findSlot(self, call_slot); - - assert(f != NULL); - - return f(self, args, kw); -} - - -/* - * The sequence type item slot. - */ -static PyObject *slot_sq_item(PyObject *self, Py_ssize_t n) -{ - PyObject *(*f)(PyObject *,PyObject *); - PyObject *arg, *res; - - if ((arg = PyLong_FromSsize_t(n)) == NULL) - return NULL; - - f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, getitem_slot); - - assert(f != NULL); - - res = f(self,arg); - - Py_DECREF(arg); - - return res; -} - - -/* - * The mapping type assign subscript slot. - */ -static int slot_mp_ass_subscript(PyObject *self, PyObject *key, - PyObject *value) -{ - return objobjargprocSlot(self, key, value, - (value != NULL ? setitem_slot : delitem_slot)); -} - - -/* - * The sequence type assign item slot. - */ -static int slot_sq_ass_item(PyObject *self, Py_ssize_t i, PyObject *o) -{ - return ssizeobjargprocSlot(self, i, o, - (o != NULL ? setitem_slot : delitem_slot)); -} - - -/* - * The type rich compare slot. - */ -static PyObject *slot_richcompare(PyObject *self, PyObject *arg, int op) -{ - PyObject *(*f)(PyObject *,PyObject *); - sipPySlotType st; - - /* Convert the operation to a slot type. */ - switch (op) - { - case Py_LT: - st = lt_slot; - break; - - case Py_LE: - st = le_slot; - break; - - case Py_EQ: - st = eq_slot; - break; - - case Py_NE: - st = ne_slot; - break; - - case Py_GT: - st = gt_slot; - break; - - case Py_GE: - st = ge_slot; - break; - } - - /* It might not exist if not all the above have been implemented. */ - if ((f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, st)) == NULL) - { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - return f(self, arg); -} - - -/* - * The __dict__ getter. - */ -static PyObject *sipSimpleWrapper_get_dict(sipSimpleWrapper *sw, void *closure) -{ - (void)closure; - - /* Create the dictionary if needed. */ - if (sw->dict == NULL) - { - sw->dict = PyDict_New(); - - if (sw->dict == NULL) - return NULL; - } - - Py_INCREF(sw->dict); - return sw->dict; -} - - -/* - * The __dict__ setter. - */ -static int sipSimpleWrapper_set_dict(sipSimpleWrapper *sw, PyObject *value, - void *closure) -{ - (void)closure; - - /* Check that any new value really is a dictionary. */ - if (value != NULL && !PyDict_Check(value)) - { - PyErr_Format(PyExc_TypeError, - "__dict__ must be set to a dictionary, not a '%s'", - Py_TYPE(value)->tp_name); - return -1; - } - - Py_XDECREF(sw->dict); - - Py_XINCREF(value); - sw->dict = value; - - return 0; -} - - -/* - * The table of getters and setters. - */ -static PyGetSetDef sipSimpleWrapper_getset[] = { - {(char *)"__dict__", (getter)sipSimpleWrapper_get_dict, - (setter)sipSimpleWrapper_set_dict, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL} -}; - - -/* - * The type data structure. Note that we pretend to be a mapping object and a - * sequence object at the same time. Python will choose one over another, - * depending on the context, but we implement as much as we can and don't make - * assumptions about which Python will choose. - */ -sipWrapperType sipSimpleWrapper_Type = { -#if !defined(STACKLESS) - { -#endif - { - PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0) - "sip.simplewrapper", /* tp_name */ - sizeof (sipSimpleWrapper), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)sipSimpleWrapper_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async (Python v3.5), 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)sipSimpleWrapper_traverse, /* tp_traverse */ - (inquiry)sipSimpleWrapper_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - sipSimpleWrapper_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(sipSimpleWrapper, dict), /* tp_dictoffset */ - (initproc)sipSimpleWrapper_init, /* tp_init */ - 0, /* tp_alloc */ - (newfunc)sipSimpleWrapper_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif - }, - { - 0, /* am_await */ - 0, /* am_aiter */ - 0, /* am_anext */ - }, - { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - 0, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - 0, /* nb_index */ - 0, /* nb_matrix_multiply */ - 0, /* nb_inplace_matrix_multiply */ - }, - { - 0, /* mp_length */ - 0, /* mp_subscript */ - 0, /* mp_ass_subscript */ - }, - { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* was_sq_slice */ - 0, /* sq_ass_item */ - 0, /* was_sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ - }, - { - 0, /* bf_getbuffer */ - 0, /* bf_releasebuffer */ - }, - 0, /* ht_name */ - 0, /* ht_slots */ - 0, /* ht_qualname */ - 0, /* ht_cached_keys */ -#if PY_VERSION_HEX >= 0x03090000 - 0, /* ht_module */ -#endif -#if !defined(STACKLESS) - }, -#endif - 0, /* wt_user_type */ - 0, /* wt_dict_complete */ - 0, /* wt_unused */ - 0, /* wt_td */ - 0, /* wt_iextend */ - 0, /* wt_new_user_type_handler */ - 0, /* wt_user_data */ -}; - - -/* - * The wrapper clear slot. - */ -static int sipWrapper_clear(sipWrapper *self) -{ - int vret; - sipSimpleWrapper *sw = (sipSimpleWrapper *)self; - - vret = sipSimpleWrapper_clear(sw); - - /* Remove any slots connected via a proxy. */ - if (sipQtSupport != NULL && sipPossibleProxy(sw) && !sipNotInMap(sw)) - { - void *tx = sip_api_get_address(sw); - - if (tx != NULL) - { - sipSlot *slot; - void *context = NULL; - - assert (sipQtSupport->qt_find_sipslot); - - while ((slot = sipQtSupport->qt_find_sipslot(tx, &context)) != NULL) - { - sip_api_clear_any_slot_reference(slot); - - if (context == NULL) - break; - } - } - } - - /* Detach any children (which will be owned by C/C++). */ - detachChildren(self); - - return vret; -} - - -/* - * The wrapper dealloc slot. - */ -static void sipWrapper_dealloc(sipWrapper *self) -{ - PyObject *error_type, *error_value, *error_traceback; - - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - /* - * We can't simply call the super-type because things have to be done in a - * certain order. The first thing is to get rid of the wrapped instance. - */ - forgetObject((sipSimpleWrapper *)self); - - sipWrapper_clear(self); - - /* Skip the super-type's dealloc. */ - PyBaseObject_Type.tp_dealloc((PyObject *)self); - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); -} - - -/* - * The wrapper traverse slot. - */ -static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg) -{ - int vret; - sipSimpleWrapper *sw = (sipSimpleWrapper *)self; - sipWrapper *w; - - if ((vret = sipSimpleWrapper_traverse(sw, visit, arg)) != 0) - return vret; - - /* - * This should be handwritten code in PyQt. The map check is a bit of a - * hack to work around PyQt4 problems with qApp and a user created - * instance. qt_find_sipslot() will return the same slot information for - * both causing the gc module to trigger assert() failures. - */ - if (sipQtSupport != NULL && sipQtSupport->qt_find_sipslot && !sipNotInMap(sw)) - { - void *tx = sip_api_get_address(sw); - - if (tx != NULL) - { - sipSlot *slot; - void *context = NULL; - - while ((slot = sipQtSupport->qt_find_sipslot(tx, &context)) != NULL) - { - if ((vret = sip_api_visit_slot(slot, visit, arg)) != 0) - return vret; - - if (context == NULL) - break; - } - } - } - - for (w = self->first_child; w != NULL; w = w->sibling_next) - { - /* - * We don't traverse if the wrapper is a child of itself. We do this - * so that wrapped objects returned by virtual methods with the - * /Factory/ don't have those objects collected. This then means that - * plugins implemented in Python have a chance of working. - */ - if (w != self) - if ((vret = visit((PyObject *)w, arg)) != 0) - return vret; - } - - return 0; -} - - -/* - * Add the slots for a class type and all its super-types. - */ -static void addClassSlots(sipWrapperType *wt, const sipClassTypeDef *ctd) -{ - PyHeapTypeObject *heap_to = &wt->super; - PyBufferProcs *bp = &heap_to->as_buffer; - - /* Add the buffer interface. */ - if (ctd->ctd_getbuffer != NULL) - bp->bf_getbuffer = (getbufferproc)sipSimpleWrapper_getbuffer; - - if (ctd->ctd_releasebuffer != NULL) - bp->bf_releasebuffer = (releasebufferproc)sipSimpleWrapper_releasebuffer; - - /* Add the slots for this type. */ - if (ctd->ctd_pyslots != NULL) - addTypeSlots(heap_to, ctd->ctd_pyslots); -} - - -/* - * Add the slot handler for each slot present in the type. - */ -static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots) -{ - PyTypeObject *to; - PyNumberMethods *nb; - PySequenceMethods *sq; - PyMappingMethods *mp; - PyAsyncMethods *am; - void *f; - - to = &heap_to->ht_type; - nb = &heap_to->as_number; - sq = &heap_to->as_sequence; - mp = &heap_to->as_mapping; - am = &heap_to->as_async; - - while ((f = slots->psd_func) != NULL) - switch (slots++->psd_type) - { - case str_slot: - to->tp_str = (reprfunc)f; - break; - - case int_slot: - nb->nb_int = (unaryfunc)f; - break; - - case float_slot: - nb->nb_float = (unaryfunc)f; - break; - - case len_slot: - mp->mp_length = (lenfunc)f; - sq->sq_length = (lenfunc)f; - break; - - case contains_slot: - sq->sq_contains = (objobjproc)f; - break; - - case add_slot: - nb->nb_add = (binaryfunc)f; - break; - - case concat_slot: - sq->sq_concat = (binaryfunc)f; - break; - - case sub_slot: - nb->nb_subtract = (binaryfunc)f; - break; - - case mul_slot: - nb->nb_multiply = (binaryfunc)f; - break; - - case repeat_slot: - sq->sq_repeat = (ssizeargfunc)f; - break; - - case div_slot: - nb->nb_true_divide = (binaryfunc)f; - break; - - case mod_slot: - nb->nb_remainder = (binaryfunc)f; - break; - - case floordiv_slot: - nb->nb_floor_divide = (binaryfunc)f; - break; - - case truediv_slot: - nb->nb_true_divide = (binaryfunc)f; - break; - - case and_slot: - nb->nb_and = (binaryfunc)f; - break; - - case or_slot: - nb->nb_or = (binaryfunc)f; - break; - - case xor_slot: - nb->nb_xor = (binaryfunc)f; - break; - - case lshift_slot: - nb->nb_lshift = (binaryfunc)f; - break; - - case rshift_slot: - nb->nb_rshift = (binaryfunc)f; - break; - - case iadd_slot: - nb->nb_inplace_add = (binaryfunc)f; - break; - - case iconcat_slot: - sq->sq_inplace_concat = (binaryfunc)f; - break; - - case isub_slot: - nb->nb_inplace_subtract = (binaryfunc)f; - break; - - case imul_slot: - nb->nb_inplace_multiply = (binaryfunc)f; - break; - - case irepeat_slot: - sq->sq_inplace_repeat = (ssizeargfunc)f; - break; - - case idiv_slot: - nb->nb_inplace_true_divide = (binaryfunc)f; - break; - - case imod_slot: - nb->nb_inplace_remainder = (binaryfunc)f; - break; - - case ifloordiv_slot: - nb->nb_inplace_floor_divide = (binaryfunc)f; - break; - - case itruediv_slot: - nb->nb_inplace_true_divide = (binaryfunc)f; - break; - - case iand_slot: - nb->nb_inplace_and = (binaryfunc)f; - break; - - case ior_slot: - nb->nb_inplace_or = (binaryfunc)f; - break; - - case ixor_slot: - nb->nb_inplace_xor = (binaryfunc)f; - break; - - case ilshift_slot: - nb->nb_inplace_lshift = (binaryfunc)f; - break; - - case irshift_slot: - nb->nb_inplace_rshift = (binaryfunc)f; - break; - - case invert_slot: - nb->nb_invert = (unaryfunc)f; - break; - - case call_slot: - to->tp_call = slot_call; - break; - - case getitem_slot: - mp->mp_subscript = (binaryfunc)f; - sq->sq_item = slot_sq_item; - break; - - case setitem_slot: - case delitem_slot: - mp->mp_ass_subscript = slot_mp_ass_subscript; - sq->sq_ass_item = slot_sq_ass_item; - break; - - case lt_slot: - case le_slot: - case eq_slot: - case ne_slot: - case gt_slot: - case ge_slot: - to->tp_richcompare = slot_richcompare; - break; - - case bool_slot: - nb->nb_bool = (inquiry)f; - break; - - case neg_slot: - nb->nb_negative = (unaryfunc)f; - break; - - case repr_slot: - to->tp_repr = (reprfunc)f; - break; - - case hash_slot: - to->tp_hash = (hashfunc)f; - break; - - case pos_slot: - nb->nb_positive = (unaryfunc)f; - break; - - case abs_slot: - nb->nb_absolute = (unaryfunc)f; - break; - - case index_slot: - nb->nb_index = (unaryfunc)f; - break; - - case iter_slot: - to->tp_iter = (getiterfunc)f; - break; - - case next_slot: - to->tp_iternext = (iternextfunc)f; - break; - - case setattr_slot: - to->tp_setattro = (setattrofunc)f; - break; - - case matmul_slot: - nb->nb_matrix_multiply = (binaryfunc)f; - break; - - case imatmul_slot: - nb->nb_inplace_matrix_multiply = (binaryfunc)f; - break; - - case await_slot: - am->am_await = (unaryfunc)f; - break; - - case aiter_slot: - am->am_aiter = (unaryfunc)f; - break; - - case anext_slot: - am->am_anext = (unaryfunc)f; - break; - - /* Suppress a compiler warning. */ - default: - ; - } -} - - -/* - * Remove the object from the map and call the C/C++ dtor if we own the - * instance. - */ -static void forgetObject(sipSimpleWrapper *sw) -{ - sipEventHandler *eh; - const sipClassTypeDef *ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(sw))->wt_td; - - /* Invoke any event handlers. */ - for (eh = event_handlers[sipEventCollectingWrapper]; eh != NULL; eh = eh->next) - { - if (is_subtype(ctd, eh->ctd)) - { - sipCollectingWrapperEventHandler handler = (sipCollectingWrapperEventHandler)eh->handler; - - handler(sw); - } - } - - /* - * This is needed because we might release the GIL when calling a C++ dtor. - * Without it the cyclic garbage collector can be invoked from another - * thread resulting in a crash. - */ - PyObject_GC_UnTrack((PyObject *)sw); - - /* - * Remove the object from the map before calling the class specific dealloc - * code. This code calls the C++ dtor and may result in further calls that - * pass the instance as an argument. If this is still in the map then it's - * reference count would be increased (to one) and bad things happen when - * it drops back to zero again. (An example is PyQt events generated - * during the dtor call being passed to an event filter implemented in - * Python.) By removing it from the map first we ensure that a new Python - * object is created. - */ - sipOMRemoveObject(&cppPyMap, sw); - - if (sipInterpreter != NULL || destroy_on_exit) - { - const sipClassTypeDef *ctd; - - if (getPtrTypeDef(sw, &ctd) != NULL && ctd->ctd_dealloc != NULL) - ctd->ctd_dealloc(sw); - } - - clear_access_func(sw); -} - - -/* - * If the given name is that of a typedef then the corresponding type is - * returned. - */ -static const char *sip_api_resolve_typedef(const char *name) -{ - const sipExportedModuleDef *em; - - /* - * Note that if the same name is defined as more than one type (which is - * possible if more than one completely independent modules are being - * used) then we might pick the wrong one. - */ - for (em = moduleList; em != NULL; em = em->em_next) - { - if (em->em_nrtypedefs > 0) - { - sipTypedefDef *tdd; - - tdd = (sipTypedefDef *)bsearch(name, em->em_typedefs, - em->em_nrtypedefs, sizeof (sipTypedefDef), - compareTypedefName); - - if (tdd != NULL) - return tdd->tdd_type_name; - } - } - - return NULL; -} - - -/* - * The bsearch() helper function for searching a sorted typedef table. - */ -static int compareTypedefName(const void *key, const void *el) -{ - return strcmp((const char *)key, ((const sipTypedefDef *)el)->tdd_name); -} - - -/* - * Add the given Python object to the given list. Return 0 if there was no - * error. - */ -static int addPyObjectToList(sipPyObject **head, PyObject *object) -{ - sipPyObject *po; - - if ((po = sip_api_malloc(sizeof (sipPyObject))) == NULL) - return -1; - - po->object = object; - po->next = *head; - - *head = po; - - return 0; -} - - -/* - * Register a symbol with a name. A negative value is returned if the name was - * already registered. - */ -static int sip_api_export_symbol(const char *name, void *sym) -{ - sipSymbol *ss; - - if (sip_api_import_symbol(name) != NULL) - return -1; - - if ((ss = sip_api_malloc(sizeof (sipSymbol))) == NULL) - return -1; - - ss->name = name; - ss->symbol = sym; - ss->next = sipSymbolList; - - sipSymbolList = ss; - - return 0; -} - - -/* - * Return the symbol registered with the given name. NULL is returned if the - * name was not registered. - */ -static void *sip_api_import_symbol(const char *name) -{ - sipSymbol *ss; - - for (ss = sipSymbolList; ss != NULL; ss = ss->next) - if (strcmp(ss->name, name) == 0) - return ss->symbol; - - return NULL; -} - - -/* - * Visit a slot connected to an object for the cyclic garbage collector. This - * would only be called externally by PyQt3. - */ -static int sip_api_visit_slot(sipSlot *slot, visitproc visit, void *arg) -{ - /* See if the slot has an extra reference. */ - if (slot->weakSlot == Py_True && slot->pyobj != Py_None) - return visit(slot->pyobj, arg); - - return 0; -} - - -/* - * Clear a slot if it has an extra reference to keep it alive. This would only - * be called externally by PyQt3. - */ -static void sip_api_clear_any_slot_reference(sipSlot *slot) -{ - if (slot->weakSlot == Py_True) - { - PyObject *xref = slot->pyobj; - - /* - * Replace the slot with None. We don't use NULL as this has another - * meaning. - */ - Py_INCREF(Py_None); - slot->pyobj = Py_None; - - Py_DECREF(xref); - } -} - - -/* - * Convert a Python object to a character and raise an exception if there was - * an error. - */ -static char sip_api_bytes_as_char(PyObject *obj) -{ - char ch; - - if (parseBytes_AsChar(obj, &ch) < 0) - { - PyErr_Format(PyExc_TypeError, "bytes of length 1 expected not '%s'", - Py_TYPE(obj)->tp_name); - - return '\0'; - } - - return ch; -} - - -/* - * Convert a Python object to a string and raise an exception if there was - * an error. - */ -static const char *sip_api_bytes_as_string(PyObject *obj) -{ - const char *a; - - if (parseBytes_AsString(obj, &a) < 0) - { - PyErr_Format(PyExc_TypeError, "bytes expected not '%s'", - Py_TYPE(obj)->tp_name); - - return NULL; - } - - return a; -} - - -/* - * Convert a Python ASCII string object to a character and raise an exception - * if there was an error. - */ -static char sip_api_string_as_ascii_char(PyObject *obj) -{ - char ch; - - if (parseString_AsASCIIChar(obj, &ch) < 0) - ch = '\0'; - - return ch; -} - - -/* - * Parse an ASCII character and return it. - */ -static int parseString_AsASCIIChar(PyObject *obj, char *ap) -{ - if (parseString_AsEncodedChar(PyUnicode_AsASCIIString(obj), obj, ap) < 0) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) - PyErr_SetString(PyExc_TypeError, - "bytes or ASCII string of length 1 expected"); - - return -1; - } - - return 0; -} - - -/* - * Convert a Python Latin-1 string object to a character and raise an exception - * if there was an error. - */ -static char sip_api_string_as_latin1_char(PyObject *obj) -{ - char ch; - - if (parseString_AsLatin1Char(obj, &ch) < 0) - ch = '\0'; - - return ch; -} - - -/* - * Parse a Latin-1 character and return it via a pointer. - */ -static int parseString_AsLatin1Char(PyObject *obj, char *ap) -{ - if (parseString_AsEncodedChar(PyUnicode_AsLatin1String(obj), obj, ap) < 0) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) - PyErr_SetString(PyExc_TypeError, - "bytes or Latin-1 string of length 1 expected"); - - return -1; - } - - return 0; -} - - -/* - * Convert a Python UTF-8 string object to a character and raise an exception - * if there was an error. - */ -static char sip_api_string_as_utf8_char(PyObject *obj) -{ - char ch; - - if (parseString_AsUTF8Char(obj, &ch) < 0) - ch = '\0'; - - return ch; -} - - -/* - * Parse a UTF-8 character and return it. - */ -static int parseString_AsUTF8Char(PyObject *obj, char *ap) -{ - if (parseString_AsEncodedChar(PyUnicode_AsUTF8String(obj), obj, ap) < 0) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) - PyErr_SetString(PyExc_TypeError, - "bytes or UTF-8 string of length 1 expected"); - - return -1; - } - - return 0; -} - - -/* - * Parse an encoded character and return it. - */ -static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap) -{ - Py_ssize_t size; - - if (bytes == NULL) - { - PyErr_Clear(); - - return parseBytes_AsChar(obj, ap); - } - - size = PyBytes_GET_SIZE(bytes); - - if (size != 1) - { - Py_DECREF(bytes); - return -1; - } - - if (ap != NULL) - *ap = *PyBytes_AS_STRING(bytes); - - Py_DECREF(bytes); - - return 0; -} - - -/* - * Convert a Python ASCII string object to a string and raise an exception if - * there was an error. The object is updated with the one that owns the - * string. Note that None is considered an error. - */ -static const char *sip_api_string_as_ascii_string(PyObject **obj) -{ - PyObject *s = *obj; - const char *a; - - if (s == Py_None || (*obj = parseString_AsASCIIString(s, &a)) == NULL) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(s)) - PyErr_Format(PyExc_TypeError, - "bytes or ASCII string expected not '%s'", - Py_TYPE(s)->tp_name); - - return NULL; - } - - return a; -} - - -/* - * Parse an ASCII string and return it and a new reference to the object that - * owns the string. - */ -static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap) -{ - return parseString_AsEncodedString(PyUnicode_AsASCIIString(obj), obj, ap); -} - - -/* - * Convert a Python Latin-1 string object to a string and raise an exception if - * there was an error. The object is updated with the one that owns the - * string. Note that None is considered an error. - */ -static const char *sip_api_string_as_latin1_string(PyObject **obj) -{ - PyObject *s = *obj; - const char *a; - - if (s == Py_None || (*obj = parseString_AsLatin1String(s, &a)) == NULL) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(s)) - PyErr_Format(PyExc_TypeError, - "bytes or Latin-1 string expected not '%s'", - Py_TYPE(s)->tp_name); - - return NULL; - } - - return a; -} - - -/* - * Parse a Latin-1 string and return it and a new reference to the object that - * owns the string. - */ -static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap) -{ - return parseString_AsEncodedString(PyUnicode_AsLatin1String(obj), obj, ap); -} - - -/* - * Convert a Python UTF-8 string object to a string and raise an exception if - * there was an error. The object is updated with the one that owns the - * string. Note that None is considered an error. - */ -static const char *sip_api_string_as_utf8_string(PyObject **obj) -{ - PyObject *s = *obj; - const char *a; - - if (s == Py_None || (*obj = parseString_AsUTF8String(s, &a)) == NULL) - { - /* Use the exception set if it was an encoding error. */ - if (!PyUnicode_Check(s)) - PyErr_Format(PyExc_TypeError, - "bytes or UTF-8 string expected not '%s'", - Py_TYPE(s)->tp_name); - - return NULL; - } - - return a; -} - - -/* - * Parse a UTF-8 string and return it and a new reference to the object that - * owns the string. - */ -static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap) -{ - return parseString_AsEncodedString(PyUnicode_AsUTF8String(obj), obj, ap); -} - - -/* - * Parse an encoded string and return it and a new reference to the object that - * owns the string. - */ -static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj, - const char **ap) -{ - if (bytes != NULL) - { - *ap = PyBytes_AS_STRING(bytes); - - return bytes; - } - - /* Don't try anything else if there was an encoding error. */ - if (PyUnicode_Check(obj)) - return NULL; - - PyErr_Clear(); - - if (parseBytes_AsString(obj, ap) < 0) - return NULL; - - Py_INCREF(obj); - - return obj; -} - - -/* - * Parse a character array and return it's address and length. - */ -static int parseBytes_AsCharArray(PyObject *obj, const char **ap, - Py_ssize_t *aszp) -{ - const char *a; - Py_ssize_t asz; - - if (obj == Py_None) - { - a = NULL; - asz = 0; - } - else if (PyBytes_Check(obj)) - { - a = PyBytes_AS_STRING(obj); - asz = PyBytes_GET_SIZE(obj); - } - else - { - Py_buffer view; - - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) - return -1; - - a = view.buf; - asz = view.len; - - PyBuffer_Release(&view); - } - - if (ap != NULL) - *ap = a; - - if (aszp != NULL) - *aszp = asz; - - return 0; -} - - -/* - * Parse a character and return it. - */ -static int parseBytes_AsChar(PyObject *obj, char *ap) -{ - const char *chp; - Py_ssize_t sz; - - if (PyBytes_Check(obj)) - { - chp = PyBytes_AS_STRING(obj); - sz = PyBytes_GET_SIZE(obj); - } - else - { - Py_buffer view; - - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) - return -1; - - chp = view.buf; - sz = view.len; - - PyBuffer_Release(&view); - } - - if (sz != 1) - return -1; - - if (ap != NULL) - *ap = *chp; - - return 0; -} - - -/* - * Parse a character string and return it. - */ -static int parseBytes_AsString(PyObject *obj, const char **ap) -{ - const char *a; - Py_ssize_t sz; - - if (parseBytes_AsCharArray(obj, &a, &sz) < 0) - return -1; - - if (ap != NULL) - *ap = a; - - return 0; -} - - -#if defined(HAVE_WCHAR_H) -/* - * Convert a Python object to a wide character. - */ -static wchar_t sip_api_unicode_as_wchar(PyObject *obj) -{ - wchar_t ch; - - if (parseWChar(obj, &ch) < 0) - { - PyErr_Format(PyExc_ValueError, - "string of length 1 expected, not %s", Py_TYPE(obj)->tp_name); - - return L'\0'; - } - - return ch; -} - - -/* - * Convert a Python object to a wide character string on the heap. - */ -static wchar_t *sip_api_unicode_as_wstring(PyObject *obj) -{ - wchar_t *p; - - if (parseWCharString(obj, &p) < 0) - { - PyErr_Format(PyExc_ValueError, - "string expected, not %s", Py_TYPE(obj)->tp_name); - - return NULL; - } - - return p; -} - - -/* - * Parse a wide character array and return it's address and length. - */ -static int parseWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp) -{ - wchar_t *a; - Py_ssize_t asz; - - if (obj == Py_None) - { - a = NULL; - asz = 0; - } - else if (PyUnicode_Check(obj)) - { - if (convertToWCharArray(obj, &a, &asz) < 0) - return -1; - } - else - { - return -1; - } - - if (ap != NULL) - *ap = a; - - if (aszp != NULL) - *aszp = asz; - - return 0; -} - - -/* - * Convert a Unicode object to a wide character array and return it's address - * and length. - */ -static int convertToWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp) -{ - Py_ssize_t ulen; - wchar_t *wc; - - ulen = PyUnicode_GET_LENGTH(obj); - - if ((wc = sip_api_malloc(ulen * sizeof (wchar_t))) == NULL) - return -1; - - if ((ulen = PyUnicode_AsWideChar(obj, wc, ulen)) < 0) - { - sip_api_free(wc); - return -1; - } - - *ap = wc; - *aszp = ulen; - - return 0; -} - - -/* - * Parse a wide character and return it. - */ -static int parseWChar(PyObject *obj, wchar_t *ap) -{ - wchar_t a; - - if (PyUnicode_Check(obj)) - { - if (convertToWChar(obj, &a) < 0) - return -1; - } - else - { - return -1; - } - - if (ap != NULL) - *ap = a; - - return 0; -} - - -/* - * Convert a Unicode object to a wide character and return it. - */ -static int convertToWChar(PyObject *obj, wchar_t *ap) -{ - if (PyUnicode_GET_LENGTH(obj) != 1) - return -1; - - if (PyUnicode_AsWideChar(obj, ap, 1) != 1) - return -1; - - return 0; -} - - -/* - * Parse a wide character string and return a copy on the heap. - */ -static int parseWCharString(PyObject *obj, wchar_t **ap) -{ - wchar_t *a; - - if (obj == Py_None) - { - a = NULL; - } - else if (PyUnicode_Check(obj)) - { - if (convertToWCharString(obj, &a) < 0) - return -1; - } - else - { - return -1; - } - - if (ap != NULL) - *ap = a; - - return 0; -} - - -/* - * Convert a Unicode object to a wide character string and return a copy on - * the heap. - */ -static int convertToWCharString(PyObject *obj, wchar_t **ap) -{ - Py_ssize_t ulen; - wchar_t *wc; - - ulen = PyUnicode_GET_LENGTH(obj); - - if ((wc = sip_api_malloc((ulen + 1) * sizeof (wchar_t))) == NULL) - return -1; - - if ((ulen = PyUnicode_AsWideChar(obj, wc, ulen)) < 0) - { - sip_api_free(wc); - return -1; - } - - wc[ulen] = L'\0'; - - *ap = wc; - - return 0; -} - -#else - -/* - * Convert a Python object to a wide character. - */ -static int sip_api_unicode_as_wchar(PyObject *obj) -{ - raiseNoWChar(); - - return 0; -} - - -/* - * Convert a Python object to a wide character. - */ -static int *sip_api_unicode_as_wstring(PyObject *obj) -{ - raiseNoWChar(); - - return NULL; -} - - -/* - * Report the need for absent wide character support. - */ -static void raiseNoWChar() -{ - PyErr_SetString(PyExc_SystemError, "sip built without wchar_t support"); -} - -#endif - - -/* - * The enum type alloc slot. - */ -static PyObject *sipEnumType_alloc(PyTypeObject *self, Py_ssize_t nitems) -{ - sipEnumTypeObject *py_type; - sipPySlotDef *psd; - - assert(currentType != NULL); - assert(sipTypeIsEnum(currentType)); - - /* Call the standard super-metatype alloc. */ - if ((py_type = (sipEnumTypeObject *)PyType_Type.tp_alloc(self, nitems)) == NULL) - return NULL; - - /* - * Set the links between the Python type object and the generated type - * structure. Strictly speaking this doesn't need to be done here. - */ - py_type->type = currentType; - currentType->td_py_type = (PyTypeObject *)py_type; - - /* - * Initialise any slots. This must be done here, after the type is - * allocated but before PyType_Ready() is called. - */ - if ((psd = ((sipEnumTypeDef *)currentType)->etd_pyslots) != NULL) - addTypeSlots(&py_type->super, psd); - - return (PyObject *)py_type; -} - - -/* - * The enum type getattro slot. - */ -static PyObject *sipEnumType_getattro(PyObject *self, PyObject *name) -{ - PyObject *res; - sipEnumTypeDef *etd; - sipExportedModuleDef *client; - const sipEnumMemberDef *enm, *emd; - int enum_nr, nr_members, m; - const char *name_str; - - /* - * Try a generic lookup first. This has the side effect of checking the - * type of the name object. - */ - if ((res = PyObject_GenericGetAttr(self, name)) != NULL) - return res; - - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return NULL; - - PyErr_Clear(); - - /* Get the member name. */ - if ((name_str = PyUnicode_AsUTF8(name)) == NULL) - return NULL; - - etd = (sipEnumTypeDef *)((sipEnumTypeObject *)self)->type; - client = ((sipTypeDef *)etd)->td_module; - - /* Find the number of this enum. */ - for (enum_nr = 0; enum_nr < client->em_nrtypes; ++enum_nr) - if (client->em_types[enum_nr] == (sipTypeDef *)etd) - break; - - /* Get the enum members in the same scope. */ - if (etd->etd_scope < 0) - { - nr_members = client->em_nrenummembers; - enm = client->em_enummembers; - } - else - { - const sipContainerDef *cod = get_container(client->em_types[etd->etd_scope]); - - nr_members = cod->cod_nrenummembers; - enm = cod->cod_enummembers; - } - - /* Find the enum member. */ - for (emd = enm, m = 0; m < nr_members; ++m, ++emd) - if (emd->em_enum == enum_nr && strcmp(emd->em_name, name_str) == 0) - return sip_api_convert_from_enum(emd->em_val, (sipTypeDef *)etd); - - PyErr_Format(PyExc_AttributeError, - "sip.enumtype object '%s' has no member '%s'", - sipPyNameOfEnum(etd), name_str); - - return NULL; -} - - -/* - * Check if an object is of the right type to convert to an encoded string. - */ -static int check_encoded_string(PyObject *obj) -{ - Py_buffer view; - - if (obj == Py_None) - return 0; - - if (PyUnicode_Check(obj)) - return 0; - - if (PyBytes_Check(obj)) - return 0; - - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) - { - PyErr_Clear(); - } - else - { - PyBuffer_Release(&view); - return 0; - } - - return -1; -} - - -/* - * This is called by the atexit module. - */ -static PyObject *sip_exit(PyObject *self, PyObject *args) -{ - (void)self; - (void)args; - - /* Disable all Python reimplementations of virtuals. */ - sipInterpreter = NULL; - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Register an exit notifier with the atexit module. - */ -static int sip_api_register_exit_notifier(PyMethodDef *md) -{ - static PyObject *register_func = NULL; - PyObject *notifier, *res; - - if (register_func == NULL && (register_func = import_module_attr("atexit", "register")) == NULL) - return -1; - - if ((notifier = PyCFunction_New(md, NULL)) == NULL) - return -1; - - res = PyObject_CallFunctionObjArgs(register_func, notifier, NULL); - - Py_DECREF(notifier); - - if (res == NULL) - return -1; - - Py_DECREF(res); - - return 0; -} - - -/* - * Return the function that converts a C++ instance to a Python object. - */ -static sipConvertFromFunc get_from_convertor(const sipTypeDef *td) -{ - if (sipTypeIsMapped(td)) - return ((const sipMappedTypeDef *)td)->mtd_cfrom; - - assert(sipTypeIsClass(td)); - - if (autoconversion_disabled(td) != NULL) - return NULL; - - return ((const sipClassTypeDef *)td)->ctd_cfrom; -} - - -/* - * Enable or disable the auto-conversion. Returns the previous enabled state - * or -1 on error. - */ -static int sip_api_enable_autoconversion(const sipTypeDef *td, int enable) -{ - sipPyObject **pop; - - assert(sipTypeIsClass(td)); - - pop = autoconversion_disabled(td); - - /* See if there is anything to do. */ - if (pop == NULL && enable) - return TRUE; - - if (pop != NULL && !enable) - return FALSE; - - if (pop != NULL) - { - /* Remove it from the list. */ - sipPyObject *po = *pop; - - *pop = po->next; - sip_api_free(po); - } - else - { - /* Add it to the list. */ - if (addPyObjectToList(&sipDisabledAutoconversions, (PyObject *)sipTypeAsPyTypeObject(td)) < 0) - return -1; - } - - return !enable; -} - - -/* - * Return a pointer to the entry in the list of disabled auto-conversions for a - * type. - */ -static sipPyObject **autoconversion_disabled(const sipTypeDef *td) -{ - PyObject *type = (PyObject *)sipTypeAsPyTypeObject(td); - sipPyObject **pop; - - for (pop = &sipDisabledAutoconversions; *pop != NULL; pop = &(*pop)->next) - if ((*pop)->object == type) - return pop; - - return NULL; -} - - -/* - * Enable or disable auto-conversion of a class that supports it. - */ -static PyObject *enableAutoconversion(PyObject *self, PyObject *args) -{ - sipWrapperType *wt; - int enable; - - (void)self; - - if (PyArg_ParseTuple(args, "O!i:enableautoconversion", &sipWrapperType_Type, &wt, &enable)) - { - sipTypeDef *td = wt->wt_td; - int was_enabled; - PyObject *res; - - if (!sipTypeIsClass(td) || ((sipClassTypeDef *)td)->ctd_cfrom == NULL) - { - PyErr_Format(PyExc_TypeError, - "%s is not a wrapped class that supports optional auto-conversion", ((PyTypeObject *)wt)->tp_name); - - return NULL; - } - - if ((was_enabled = sip_api_enable_autoconversion(td, enable)) < 0) - return NULL; - - res = (was_enabled ? Py_True : Py_False); - - Py_INCREF(res); - return res; - } - - return NULL; -} - - -/* - * Python copies the nb_inplace_add slot to the sq_inplace_concat slot and vice - * versa if either are missing. This is a bug because they don't have the same - * API. We therefore reverse this. - */ -static void fix_slots(PyTypeObject *py_type, sipPySlotDef *psd) -{ - while (psd->psd_func != NULL) - { - if (psd->psd_type == iadd_slot && py_type->tp_as_sequence != NULL) - py_type->tp_as_sequence->sq_inplace_concat = NULL; - - if (psd->psd_type == iconcat_slot && py_type->tp_as_number != NULL) - py_type->tp_as_number->nb_inplace_add = NULL; - - ++psd; - } -} - - -/* - * Return the main instance for an object if it is a mixin. - */ -static sipSimpleWrapper *deref_mixin(sipSimpleWrapper *w) -{ - return w->mixin_main != NULL ? (sipSimpleWrapper *)w->mixin_main : w; -} - - -/* - * Convert a new C/C++ pointer to a Python instance. - */ -static PyObject *wrap_simple_instance(void *cpp, const sipTypeDef *td, - sipWrapper *owner, int flags) -{ - return sipWrapInstance(cpp, sipTypeAsPyTypeObject(td), empty_tuple, owner, - flags); -} - - -/* - * Resolve a proxy, if applicable. - */ -static void *resolve_proxy(const sipTypeDef *td, void *proxy) -{ - sipProxyResolver *pr; - - /* TODO: Deprecate this mechanism in favour of an event handler. */ - for (pr = proxyResolvers; pr != NULL; pr = pr->next) - if (pr->td == td) - proxy = pr->resolver(proxy); - - return proxy; -} - - -/* - * Clear a simple wrapper. - */ -static void clear_wrapper(sipSimpleWrapper *sw) -{ - if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type)) - removeFromParent((sipWrapper *)sw); - - /* - * Transfer ownership to C++ so we don't try to release it when the - * Python object is garbage collected. - */ - sipResetPyOwned(sw); - - sipOMRemoveObject(&cppPyMap, sw); - - clear_access_func(sw); -} - - -/* - * Set the handler to invoke when a new user Python sub-class is defined and - * return the old handler. - */ -static sipNewUserTypeFunc sip_api_set_new_user_type_handler( - const sipTypeDef *td, sipNewUserTypeFunc handler) -{ - sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td); - sipNewUserTypeFunc old_handler = wt->wt_new_user_type_handler;; - - wt->wt_new_user_type_handler = handler; - - return old_handler; -} - - -/* - * Set the user-specific type data. - */ -static void sip_api_set_type_user_data(sipWrapperType *wt, void *data) -{ - wt->wt_user_data = data; -} - - -/* - * Get the user-specific type data. - */ -static void *sip_api_get_type_user_data(const sipWrapperType *wt) -{ - return wt->wt_user_data; -} - - -/* - * Get the dict of a Python type (on behalf of the limited API). - */ -static PyObject *sip_api_py_type_dict(const PyTypeObject *py_type) -{ - return py_type->tp_dict; -} - - -/* - * Get the name of a Python type (on behalf of the limited API). - */ -static const char *sip_api_py_type_name(const PyTypeObject *py_type) -{ - return py_type->tp_name; -} - - -/* - * Check an object is a method and return TRUE and its component parts if it - * is. - */ -static int sip_api_get_method(PyObject *obj, sipMethodDef *method) -{ - if (!PyMethod_Check(obj)) - return FALSE; - - if (method != NULL) - { - method->pm_self = PyMethod_GET_SELF(obj); - method->pm_function = PyMethod_GET_FUNCTION(obj); - } - - return TRUE; -} - - -/* - * Create a method from its component parts. - */ -static PyObject *sip_api_from_method(const sipMethodDef *method) -{ - return PyMethod_New(method->pm_function, method->pm_self); -} - - -/* - * Check an object is a C function and return TRUE and its component parts if - * it is. - */ -static int sip_api_get_c_function(PyObject *obj, sipCFunctionDef *c_function) -{ - if (!PyCFunction_Check(obj)) - return FALSE; - - if (c_function != NULL) - { - c_function->cf_function = ((PyCFunctionObject *)obj)->m_ml; - c_function->cf_self = PyCFunction_GET_SELF(obj); - } - - return TRUE; -} - - -/* - * Check an object is a date and return TRUE and its component parts if it is. - */ -static int sip_api_get_date(PyObject *obj, sipDateDef *date) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - if (!PyDate_Check(obj)) - return FALSE; - - if (date != NULL) - { - date->pd_year = PyDateTime_GET_YEAR(obj); - date->pd_month = PyDateTime_GET_MONTH(obj); - date->pd_day = PyDateTime_GET_DAY(obj); - } - - return TRUE; -} - - -/* - * Create a date from its component parts. - */ -static PyObject *sip_api_from_date(const sipDateDef *date) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - return PyDate_FromDate(date->pd_year, date->pd_month, date->pd_day); -} - - -/* - * Check an object is a datetime and return TRUE and its component parts if it - * is. - */ -static int sip_api_get_datetime(PyObject *obj, sipDateDef *date, - sipTimeDef *time) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - if (!PyDateTime_Check(obj)) - return FALSE; - - if (date != NULL) - { - date->pd_year = PyDateTime_GET_YEAR(obj); - date->pd_month = PyDateTime_GET_MONTH(obj); - date->pd_day = PyDateTime_GET_DAY(obj); - } - - if (time != NULL) - { - time->pt_hour = PyDateTime_DATE_GET_HOUR(obj); - time->pt_minute = PyDateTime_DATE_GET_MINUTE(obj); - time->pt_second = PyDateTime_DATE_GET_SECOND(obj); - time->pt_microsecond = PyDateTime_DATE_GET_MICROSECOND(obj); - } - - return TRUE; -} - - -/* - * Create a datetime from its component parts. - */ -static PyObject *sip_api_from_datetime(const sipDateDef *date, - const sipTimeDef *time) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - return PyDateTime_FromDateAndTime(date->pd_year, date->pd_month, - date->pd_day, time->pt_hour, time->pt_minute, time->pt_second, - time->pt_microsecond); -} - - -/* - * Check an object is a time and return TRUE and its component parts if it is. - */ -static int sip_api_get_time(PyObject *obj, sipTimeDef *time) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - if (!PyTime_Check(obj)) - return FALSE; - - if (time != NULL) - { - time->pt_hour = PyDateTime_TIME_GET_HOUR(obj); - time->pt_minute = PyDateTime_TIME_GET_MINUTE(obj); - time->pt_second = PyDateTime_TIME_GET_SECOND(obj); - time->pt_microsecond = PyDateTime_TIME_GET_MICROSECOND(obj); - } - - return TRUE; -} - - -/* - * Create a time from its component parts. - */ -static PyObject *sip_api_from_time(const sipTimeDef *time) -{ - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - - return PyTime_FromTime(time->pt_hour, time->pt_minute, time->pt_second, - time->pt_microsecond); -} - - -/* - * See if a type is user defined. - */ -static int sip_api_is_user_type(const sipWrapperType *wt) -{ - return wt->wt_user_type; -} - - -/* - * Return a frame from the execution stack. - */ -static struct _frame *sip_api_get_frame(int depth) -{ -#if defined(PYPY_VERSION) - /* PyPy only supports a depth of 0. */ - return NULL; -#else - struct _frame *frame = PyEval_GetFrame(); - - while (frame != NULL && depth > 0) - { - frame = frame->f_back; - --depth; - } - - return frame; -#endif -} - - -/* - * Check if a type was generated using the given plugin. Note that, although - * this is part of the public API it is undocumented on purpose. - */ -static int sip_api_check_plugin_for_type(const sipTypeDef *td, - const char *name) -{ - /* - * The current thinking on plugins is that SIP v5 will look for a plugin - * with a name derived from the name as the current module in the same - * directory as the .sip defining the module (ie. no %Plugin directive). A - * module hierarchy may have multiple plugins but they must co-operate. If - * a plugin generates user data then it should include a void* (and a - * run-time API) so that other plugins can extend it further. This - * approach means that a plugin's user data structure can be opaque. - */ - - sipExportedModuleDef *em = td->td_module; - sipImportedModuleDef *im; - - if (strcmp(sipNameOfModule(em), name) == 0) - return TRUE; - - if ((im = em->em_imports) == NULL) - return FALSE; - - while (im->im_name != NULL) - { - if (strcmp(im->im_name, name) == 0) - return TRUE; - - ++im; - } - - return FALSE; -} - - -/* - * Create a new Unicode object and return the character size and buffer. - */ -static PyObject *sip_api_unicode_new(Py_ssize_t len, unsigned maxchar, - int *kind, void **data) -{ - PyObject *obj; - - if ((obj = PyUnicode_New(len, maxchar)) != NULL) - { - *kind = PyUnicode_KIND(obj); - *data = PyUnicode_DATA(obj); - } - - return obj; -} - - -/* - * Update a new Unicode object with a new character. - */ -static void sip_api_unicode_write(int kind, void *data, int index, - unsigned value) -{ - PyUnicode_WRITE(kind, data, index, value); -} - - -/* - * Get the address of the contents of a Unicode object, the character size and - * the length. - */ -static void *sip_api_unicode_data(PyObject *obj, int *char_size, - Py_ssize_t *len) -{ - void *data; - - /* Assume there will be an error. */ - *char_size = -1; - - if (PyUnicode_READY(obj) < 0) - return NULL; - - *len = PyUnicode_GET_LENGTH(obj); - - switch (PyUnicode_KIND(obj)) - { - case PyUnicode_1BYTE_KIND: - *char_size = 1; - data = PyUnicode_1BYTE_DATA(obj); - break; - - case PyUnicode_2BYTE_KIND: - *char_size = 2; - data = PyUnicode_2BYTE_DATA(obj); - break; - - case PyUnicode_4BYTE_KIND: - *char_size = 4; - data = PyUnicode_4BYTE_DATA(obj); - break; - - default: - data = NULL; - } - - return data; -} - - -/* - * Get the buffer information supplied by an object that supports the buffer - * protocol. - */ -static int sip_api_get_buffer_info(PyObject *obj, sipBufferInfoDef *bi) -{ - int rc; - Py_buffer *buffer; - - if (!PyObject_CheckBuffer(obj)) - return 0; - - if (bi == NULL) - return 1; - - if ((bi->bi_internal = sip_api_malloc(sizeof (Py_buffer))) == NULL) - return -1; - - buffer = (Py_buffer *)bi->bi_internal; - - if (PyObject_GetBuffer(obj, buffer, PyBUF_FORMAT) < 0) - return -1; - - if (buffer->ndim == 1) - { - bi->bi_buf = buffer->buf; - bi->bi_obj = buffer->obj; - bi->bi_len = buffer->len; - bi->bi_format = buffer->format; - - rc = 1; - } - else - { - PyErr_SetString(PyExc_TypeError, "a 1-dimensional buffer is required"); - PyBuffer_Release(buffer); - rc = -1; - } - - return rc; -} - - -/* - * Release the buffer information obtained from a previous call to - * sipGetBufferInfo(). - */ -static void sip_api_release_buffer_info(sipBufferInfoDef *bi) -{ - if (bi->bi_internal != NULL) - { - PyBuffer_Release((Py_buffer *)bi->bi_internal); - sip_api_free(bi->bi_internal); - bi->bi_internal = NULL; - } -} - - -/* - * Import all the required types from an imported module. - */ -static int importTypes(sipExportedModuleDef *client, sipImportedModuleDef *im, - sipExportedModuleDef *em) -{ - const char *name; - int i, e; - - /* - * Look for each required type in turn. Both tables are sorted so a single - * pass will find them all. - */ - for (i = e = 0; (name = im->im_imported_types[i].it_name) != NULL; ++i) - { - sipTypeDef *td = NULL; - - do - { - sipTypeDef *e_td; - - if (e >= em->em_nrtypes) - { - PyErr_Format(PyExc_RuntimeError, - "%s cannot import type '%s' from %s", - sipNameOfModule(client), name, sipNameOfModule(em)); - - return -1; - } - - e_td = em->em_types[e++]; - - /* Ignore unresolved external types. */ - if (e_td != NULL && strcmp(name, sipTypeName(e_td)) == 0) - td = e_td; - } - while (td == NULL); - - im->im_imported_types[i].it_td = td; - } - - return 0; -} - - -/* - * Import all the required virtual error handlers from an imported module. - */ -static int importErrorHandlers(sipExportedModuleDef *client, - sipImportedModuleDef *im, sipExportedModuleDef *em) -{ - const char *name; - int i; - - for (i = 0; (name = im->im_imported_veh[i].iveh_name) != NULL; ++i) - { - sipVirtErrorHandlerDef *veh = em->em_virterrorhandlers; - sipVirtErrorHandlerFunc handler = NULL; - - if (veh != NULL) - { - while (veh->veh_name != NULL) - { - if (strcmp(veh->veh_name, name) == 0) - { - handler = veh->veh_handler; - break; - } - - ++veh; - } - } - - if (handler == NULL) - { - PyErr_Format(PyExc_RuntimeError, - "%s cannot import virtual error handler '%s' from %s", - sipNameOfModule(client), name, sipNameOfModule(em)); - - return -1; - } - - im->im_imported_veh[i].iveh_handler = handler; - } - - return 0; -} - - -/* - * Import all the required exceptions from an imported module. - */ -static int importExceptions(sipExportedModuleDef *client, - sipImportedModuleDef *im, sipExportedModuleDef *em) -{ - const char *name; - int i; - - for (i = 0; (name = im->im_imported_exceptions[i].iexc_name) != NULL; ++i) - { - PyObject **exc = em->em_exceptions; - PyObject *exception = NULL; - - if (exc != NULL) - { - while (*exc != NULL) - { - if (strcmp(((PyTypeObject *)(*exc))->tp_name, name) == 0) - { - exception = *exc; - break; - } - - ++exc; - } - } - - if (exception == NULL) - { - PyErr_Format(PyExc_RuntimeError, - "%s cannot import exception '%s' from %s", - sipNameOfModule(client), name, sipNameOfModule(em)); - - return -1; - } - - im->im_imported_exceptions[i].iexc_object = exception; - } - - return 0; -} - - -/* - * Enable or disable the garbage collector. Return the previous state or -1 if - * there was an error. - */ -static int sip_api_enable_gc(int enable) -{ - static PyObject *enable_func = NULL, *disable_func, *isenabled_func; - PyObject *result; - int was_enabled; - - /* - * This may be -ve in the highly unusual event that a previous call failed. - */ - if (enable < 0) - return -1; - - /* Get the functions if we haven't already got them. */ - if (enable_func == NULL) - { - PyObject *gc_module; - - if ((gc_module = PyImport_ImportModule("gc")) == NULL) - return -1; - - if ((enable_func = PyObject_GetAttrString(gc_module, "enable")) == NULL) - { - Py_DECREF(gc_module); - return -1; - } - - if ((disable_func = PyObject_GetAttrString(gc_module, "disable")) == NULL) - { - Py_DECREF(enable_func); - Py_DECREF(gc_module); - return -1; - } - - if ((isenabled_func = PyObject_GetAttrString(gc_module, "isenabled")) == NULL) - { - Py_DECREF(disable_func); - Py_DECREF(enable_func); - Py_DECREF(gc_module); - return -1; - } - - Py_DECREF(gc_module); - } - - /* Get the current state. */ - if ((result = PyObject_Call(isenabled_func, empty_tuple, NULL)) == NULL) - return -1; - - was_enabled = PyObject_IsTrue(result); - Py_DECREF(result); - - if (was_enabled < 0) - return -1; - - /* See if the state needs changing. */ - if (!was_enabled != !enable) - { - /* Enable or disable as required. */ - result = PyObject_Call((enable ? enable_func : disable_func), - empty_tuple, NULL); - - Py_XDECREF(result); - - if (result != Py_None) - return -1; - } - - return was_enabled; -} - - -/* - * A thin wrapper around PyObject_Print() usually used when debugging with the - * limited API. - */ -static void sip_api_print_object(PyObject *o) -{ - PyObject_Print(o, stdout, 0); -} - - -/* - * Register a handler for a particular event. - */ -static int sip_api_register_event_handler(sipEventType type, - const sipTypeDef *td, void *handler) -{ - sipEventHandler *eh; - - assert(sipTypeIsClass(td)); - - if ((eh = sip_api_malloc(sizeof (sipEventHandler))) == NULL) - return -1; - - eh->ctd = (const sipClassTypeDef *)td; - eh->handler = handler; - - eh->next = event_handlers[(int)type]; - event_handlers[(int)type] = eh; - - return 0; -} - - -/* - * Returns TRUE if a generated class type is a sub-class of a base generated - * class type. - */ -static int is_subtype(const sipClassTypeDef *ctd, - const sipClassTypeDef *base_ctd) -{ - const sipEncodedTypeDef *sup; - - /* Handle the trivial cases. */ - if (ctd == base_ctd) - return TRUE; - - if ((sup = ctd->ctd_supers) == NULL) - return FALSE; - - /* Search the super-types. */ - do - { - const sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); - - if (is_subtype(sup_ctd, base_ctd)) - return TRUE; - } - while (!sup++->sc_flag); - - return FALSE; -} - - -/* - * Return an attribute of an imported module. - */ -static PyObject *import_module_attr(const char *module, const char *attr) -{ - PyObject *mod_obj, *attr_obj; - - if ((mod_obj = PyImport_ImportModule(module)) == NULL) - return NULL; - - attr_obj = PyObject_GetAttrString(mod_obj, attr); - - Py_DECREF(mod_obj); - - return attr_obj; -} - - -/* - * Get the container for a generated type. - */ -static const sipContainerDef *get_container(const sipTypeDef *td) -{ - if (sipTypeIsMapped(td)) - return &((const sipMappedTypeDef *)td)->mtd_container; - - return &((const sipClassTypeDef *)td)->ctd_container; -} - - -/* - * Get the __qualname__ of an object based on its enclosing scope. - */ -static PyObject *get_qualname(const sipTypeDef *td, PyObject *name) -{ - PyTypeObject *scope_type; - - /* Get the type that is the scope. */ - scope_type = sipTypeAsPyTypeObject(td); - - return PyUnicode_FromFormat("%U.%U", - ((PyHeapTypeObject *)scope_type)->ht_qualname, name); -} - - -/* - * Implement PySlice_GetIndicesEx() (or its subsequent replacement). - */ -int sip_api_convert_from_slice_object(PyObject *slice, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, - Py_ssize_t *slicelength) -{ -#if PY_VERSION_HEX >= 0x03070000 - if (PySlice_Unpack(slice, start, stop, step) < 0) - return -1; - - *slicelength = PySlice_AdjustIndices(length, start, stop, *step); - - return 0; -#else - return PySlice_GetIndicesEx(slice, length, start, stop, step, slicelength); -#endif -} - - -/* - * Call a visitor function for every wrapped object. - */ -static void sip_api_visit_wrappers(sipWrapperVisitorFunc visitor, - void *closure) -{ - const sipHashEntry *he; - unsigned long i; - - for (he = cppPyMap.hash_array, i = 0; i < cppPyMap.size; ++i, ++he) - { - if (he->key != NULL) - { - sipSimpleWrapper *sw; - - for (sw = he->first; sw != NULL; sw = sw->next) - visitor(sw, closure); - } - } -} diff --git a/sip/siplib/threads.c b/sip/siplib/threads.c deleted file mode 100644 index bb6d50ce..00000000 --- a/sip/siplib/threads.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Thread support for the SIP library. This module provides the hooks for - * C++ classes that provide a thread interface to interact properly with the - * Python threading infrastructure. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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 "sipint.h" - - -/* - * The data associated with pending request to wrap an object. - */ -typedef struct _pendingDef { - void *cpp; /* The C/C++ object ot be wrapped. */ - sipWrapper *owner; /* The owner of the object. */ - int flags; /* The flags. */ -} pendingDef; - - -#ifdef WITH_THREAD - -#include - - -/* - * The per thread data we need to maintain. - */ -typedef struct _threadDef { - long thr_ident; /* The thread identifier. */ - pendingDef pending; /* An object waiting to be wrapped. */ - struct _threadDef *next; /* Next in the list. */ -} threadDef; - -static threadDef *threads = NULL; /* Linked list of threads. */ - -static threadDef *currentThreadDef(int auto_alloc); - -#endif - - -static pendingDef *get_pending(int auto_alloc); - - -/* - * Get the address etc. of any C/C++ object waiting to be wrapped. - */ -int sipGetPending(void **pp, sipWrapper **op, int *fp) -{ - pendingDef *pd; - - if ((pd = get_pending(TRUE)) == NULL) - return -1; - - *pp = pd->cpp; - *op = pd->owner; - *fp = pd->flags; - - /* Clear in case we execute Python code before finishing this wrapping. */ - pd->cpp = NULL; - - return 0; -} - - -/* - * Return TRUE if anything is pending. - */ -int sipIsPending(void) -{ - pendingDef *pd; - - if ((pd = get_pending(FALSE)) == NULL) - return FALSE; - - return (pd->cpp != NULL); -} - - -/* - * Convert a new C/C++ pointer to a Python instance. - */ -PyObject *sipWrapInstance(void *cpp, PyTypeObject *py_type, PyObject *args, - sipWrapper *owner, int flags) -{ - pendingDef old_pending, *pd; - PyObject *self; - - if (cpp == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - /* - * Object creation can trigger the Python garbage collector which in turn - * can execute arbitrary Python code which can then call this function - * recursively. Therefore we save any existing pending object before - * setting the new one. - */ - if ((pd = get_pending(TRUE)) == NULL) - return NULL; - - old_pending = *pd; - - pd->cpp = cpp; - pd->owner = owner; - pd->flags = flags; - - self = PyObject_Call((PyObject *)py_type, args, NULL); - - *pd = old_pending; - - return self; -} - - -/* - * Handle the termination of a thread. - */ -void sip_api_end_thread(void) -{ -#ifdef WITH_THREAD - threadDef *thread; - PyGILState_STATE gil = PyGILState_Ensure(); - - if ((thread = currentThreadDef(FALSE)) != NULL) - thread->thr_ident = 0; - - PyGILState_Release(gil); -#endif -} - - -/* - * Return the pending data for the current thread, allocating it if necessary, - * or NULL if there was an error. - */ -static pendingDef *get_pending(int auto_alloc) -{ -#ifdef WITH_THREAD - threadDef *thread; - - if ((thread = currentThreadDef(auto_alloc)) == NULL) - return NULL; - - return &thread->pending; -#else - static pendingDef pending; - - return &pending; -#endif -} - - -#ifdef WITH_THREAD - -/* - * Return the thread data for the current thread, allocating it if necessary, - * or NULL if there was an error. - */ -static threadDef *currentThreadDef(int auto_alloc) -{ - threadDef *thread, *empty = NULL; - long ident = PyThread_get_thread_ident(); - - /* See if we already know about the thread. */ - for (thread = threads; thread != NULL; thread = thread->next) - { - if (thread->thr_ident == ident) - return thread; - - if (thread->thr_ident == 0) - empty = thread; - } - - if (!auto_alloc) - { - /* This is not an error. */ - return NULL; - } - - if (empty != NULL) - { - /* Use an empty entry in the list. */ - thread = empty; - } - else if ((thread = sip_api_malloc(sizeof (threadDef))) == NULL) - { - return NULL; - } - else - { - thread->next = threads; - threads = thread; - } - - thread->thr_ident = ident; - thread->pending.cpp = NULL; - - return thread; -} - -#endif diff --git a/sip/siplib/voidptr.c b/sip/siplib/voidptr.c deleted file mode 100644 index bc7062d8..00000000 --- a/sip/siplib/voidptr.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * SIP library code. - * - * Copyright (c) 2019 Riverbank Computing Limited - * - * 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 - -#include -#include - -#include "sipint.h" -#include "array.h" - - -/* The object data structure. */ -typedef struct { - PyObject_HEAD - void *voidptr; - Py_ssize_t size; - int rw; -} sipVoidPtrObject; - - -/* The structure used to hold the results of a voidptr conversion. */ -struct vp_values { - void *voidptr; - Py_ssize_t size; - int rw; -}; - - -static int check_size(PyObject *self); -static int check_rw(PyObject *self); -static int check_index(PyObject *self, Py_ssize_t idx); -static void bad_key(PyObject *key); -static int check_slice_size(Py_ssize_t size, Py_ssize_t value_size); -static PyObject *make_voidptr(void *voidptr, Py_ssize_t size, int rw); -static int vp_convertor(PyObject *arg, struct vp_values *vp); -static Py_ssize_t get_size_from_arg(sipVoidPtrObject *v, Py_ssize_t size); - - -/* - * Implement ascapsule() for the type. - */ -static PyObject *sipVoidPtr_ascapsule(sipVoidPtrObject *v, PyObject *arg) -{ - (void)arg; - - return PyCapsule_New(v->voidptr, NULL, NULL); -} - - -/* - * Implement asarray() for the type. - */ -static PyObject *sipVoidPtr_asarray(sipVoidPtrObject *v, PyObject *args, - PyObject *kw) -{ - static char *kwlist[] = {"size", NULL}; - - Py_ssize_t size = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|n:asarray", kwlist, &size)) - return NULL; - - if ((size = get_size_from_arg(v, size)) < 0) - return NULL; - - return sip_api_convert_to_array(v->voidptr, "B", size, - (v->rw ? 0 : SIP_READ_ONLY)); -} - - -/* - * Implement asstring() for the type. - */ -static PyObject *sipVoidPtr_asstring(sipVoidPtrObject *v, PyObject *args, - PyObject *kw) -{ - static char *kwlist[] = {"size", NULL}; - - Py_ssize_t size = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|n:asstring", kwlist, &size)) - return NULL; - - if ((size = get_size_from_arg(v, size)) < 0) - return NULL; - - return PyBytes_FromStringAndSize(v->voidptr, size); -} - - -/* - * Implement getsize() for the type. - */ -static PyObject *sipVoidPtr_getsize(sipVoidPtrObject *v, PyObject *arg) -{ - (void)arg; - - return PyLong_FromSsize_t(v->size); -} - - -/* - * Implement setsize() for the type. - */ -static PyObject *sipVoidPtr_setsize(sipVoidPtrObject *v, PyObject *arg) -{ - Py_ssize_t size = PyLong_AsSsize_t(arg); - - if (PyErr_Occurred()) - return NULL; - - v->size = size; - - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Implement getwriteable() for the type. - */ -static PyObject *sipVoidPtr_getwriteable(sipVoidPtrObject *v, PyObject *arg) -{ - (void)arg; - - return PyBool_FromLong(v->rw); -} - - -/* - * Implement setwriteable() for the type. - */ -static PyObject *sipVoidPtr_setwriteable(sipVoidPtrObject *v, PyObject *arg) -{ - int rw; - - if ((rw = PyObject_IsTrue(arg)) < 0) - return NULL; - - v->rw = rw; - - Py_INCREF(Py_None); - return Py_None; -} - - -/* The methods data structure. */ -static PyMethodDef sipVoidPtr_Methods[] = { - {"asarray", (PyCFunction)sipVoidPtr_asarray, METH_VARARGS|METH_KEYWORDS, NULL}, - {"ascapsule", (PyCFunction)sipVoidPtr_ascapsule, METH_NOARGS, NULL}, - {"asstring", (PyCFunction)sipVoidPtr_asstring, METH_VARARGS|METH_KEYWORDS, NULL}, - {"getsize", (PyCFunction)sipVoidPtr_getsize, METH_NOARGS, NULL}, - {"setsize", (PyCFunction)sipVoidPtr_setsize, METH_O, NULL}, - {"getwriteable", (PyCFunction)sipVoidPtr_getwriteable, METH_NOARGS, NULL}, - {"setwriteable", (PyCFunction)sipVoidPtr_setwriteable, METH_O, NULL}, - {NULL, NULL, 0, NULL} -}; - - -/* - * Implement bool() for the type. - */ -static int sipVoidPtr_bool(PyObject *self) -{ - return (((sipVoidPtrObject *)self)->voidptr != NULL); -} - - -/* - * Implement int() for the type. - */ -static PyObject *sipVoidPtr_int(PyObject *self) -{ - return PyLong_FromVoidPtr(((sipVoidPtrObject *)self)->voidptr); -} - - -/* The number methods data structure. */ -static PyNumberMethods sipVoidPtr_NumberMethods = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - sipVoidPtr_bool, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - sipVoidPtr_int, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - 0, /* nb_index */ - 0, /* nb_matrix_multiply */ - 0, /* nb_inplace_matrix_multiply */ -}; - - -/* - * Implement len() for the type. - */ -static Py_ssize_t sipVoidPtr_length(PyObject *self) -{ - if (check_size(self) < 0) - return -1; - - return ((sipVoidPtrObject *)self)->size; -} - - -/* - * Implement sequence item sub-script for the type. - */ -static PyObject *sipVoidPtr_item(PyObject *self, Py_ssize_t idx) -{ - if (check_size(self) < 0 || check_index(self, idx) < 0) - return NULL; - - return PyBytes_FromStringAndSize( - (char *)((sipVoidPtrObject *)self)->voidptr + idx, 1); -} - - -/* The sequence methods data structure. */ -static PySequenceMethods sipVoidPtr_SequenceMethods = { - sipVoidPtr_length, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - sipVoidPtr_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - - -/* - * Implement mapping sub-script for the type. - */ -static PyObject *sipVoidPtr_subscript(PyObject *self, PyObject *key) -{ - sipVoidPtrObject *v; - - if (check_size(self) < 0) - return NULL; - - v = (sipVoidPtrObject *)self; - - if (PyIndex_Check(key)) - { - Py_ssize_t idx = PyNumber_AsSsize_t(key, PyExc_IndexError); - - if (idx == -1 && PyErr_Occurred()) - return NULL; - - if (idx < 0) - idx += v->size; - - return sipVoidPtr_item(self, idx); - } - - if (PySlice_Check(key)) - { - Py_ssize_t start, stop, step, slicelength; - - if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &slicelength) < 0) - return NULL; - - if (step != 1) - { - PyErr_SetNone(PyExc_NotImplementedError); - return NULL; - } - - return make_voidptr((char *)v->voidptr + start, slicelength, v->rw); - } - - bad_key(key); - - return NULL; -} - - -/* - * Implement mapping assignment sub-script for the type. - */ -static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, - PyObject *value) -{ - sipVoidPtrObject *v; - Py_ssize_t start, size; - Py_buffer value_view; - - if (check_rw(self) < 0 || check_size(self) < 0) - return -1; - - v = (sipVoidPtrObject *)self; - - if (PyIndex_Check(key)) - { - start = PyNumber_AsSsize_t(key, PyExc_IndexError); - - if (start == -1 && PyErr_Occurred()) - return -1; - - if (start < 0) - start += v->size; - - if (check_index(self, start) < 0) - return -1; - - size = 1; - } - else if (PySlice_Check(key)) - { - Py_ssize_t stop, step; - - if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &size) < 0) - return -1; - - if (step != 1) - { - PyErr_SetNone(PyExc_NotImplementedError); - return -1; - } - } - else - { - bad_key(key); - - return -1; - } - - if (PyObject_GetBuffer(value, &value_view, PyBUF_CONTIG_RO) < 0) - return -1; - - /* We could allow any item size... */ - if (value_view.itemsize != 1) - { - PyErr_Format(PyExc_TypeError, "'%s' must have an item size of 1", - Py_TYPE(value_view.obj)->tp_name); - - PyBuffer_Release(&value_view); - return -1; - } - - if (check_slice_size(size, value_view.len) < 0) - { - PyBuffer_Release(&value_view); - return -1; - } - - memmove((char *)v->voidptr + start, value_view.buf, size); - - PyBuffer_Release(&value_view); - - return 0; -} - - -/* The mapping methods data structure. */ -static PyMappingMethods sipVoidPtr_MappingMethods = { - sipVoidPtr_length, /* mp_length */ - sipVoidPtr_subscript, /* mp_subscript */ - sipVoidPtr_ass_subscript, /* mp_ass_subscript */ -}; - - -/* - * The buffer implementation for Python v2.6.3 and later. - */ -static int sipVoidPtr_getbuffer(PyObject *self, Py_buffer *buf, int flags) -{ - sipVoidPtrObject *v; - - if (check_size(self) < 0) - return -1; - - v = (sipVoidPtrObject *)self; - - return PyBuffer_FillInfo(buf, self, v->voidptr, v->size, !v->rw, flags); -} - - -/* The buffer methods data structure. */ -static PyBufferProcs sipVoidPtr_BufferProcs = { - sipVoidPtr_getbuffer, /* bf_getbuffer */ - 0 /* bf_releasebuffer */ -}; - - -/* - * Implement __new__ for the type. - */ -static PyObject *sipVoidPtr_new(PyTypeObject *subtype, PyObject *args, - PyObject *kw) -{ - static char *kwlist[] = {"address", "size", "writeable", NULL}; - - struct vp_values vp_conversion; - Py_ssize_t size = -1; - int rw = -1; - PyObject *obj; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "O&|ni:voidptr", kwlist, vp_convertor, &vp_conversion, &size, &rw)) - return NULL; - - /* Use the explicit size if one was given. */ - if (size >= 0) - vp_conversion.size = size; - - /* Use the explicit writeable flag if one was given. */ - if (rw >= 0) - vp_conversion.rw = rw; - - /* Create the instance. */ - if ((obj = subtype->tp_alloc(subtype, 0)) == NULL) - return NULL; - - /* Save the values. */ - ((sipVoidPtrObject *)obj)->voidptr = vp_conversion.voidptr; - ((sipVoidPtrObject *)obj)->size = vp_conversion.size; - ((sipVoidPtrObject *)obj)->rw = vp_conversion.rw; - - return obj; -} - - -/* The type data structure. */ -PyTypeObject sipVoidPtr_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "sip.voidptr", /* tp_name */ - sizeof (sipVoidPtrObject), /* 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 */ - &sipVoidPtr_NumberMethods, /* tp_as_number */ - &sipVoidPtr_SequenceMethods, /* tp_as_sequence */ - &sipVoidPtr_MappingMethods, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &sipVoidPtr_BufferProcs, /* tp_as_buffer */ -#if defined(Py_TPFLAGS_HAVE_NEWBUFFER) - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ -#else - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ -#endif - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - sipVoidPtr_Methods, /* 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 */ - sipVoidPtr_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -}; - - -/* - * A convenience function to convert a C/C++ void pointer from a Python object. - */ -void *sip_api_convert_to_void_ptr(PyObject *obj) -{ - struct vp_values vp; - - if (obj == NULL) - { - PyErr_SetString(PyExc_TypeError, "sip.voidptr is NULL"); - return NULL; - } - - if (vp_convertor(obj, &vp)) - return vp.voidptr; - - return PyLong_AsVoidPtr(obj); -} - - -/* - * Convert a C/C++ void pointer to a sip.voidptr object. - */ -PyObject *sip_api_convert_from_void_ptr(void *val) -{ - return make_voidptr(val, -1, TRUE); -} - - -/* - * Convert a C/C++ void pointer to a sip.voidptr object. - */ -PyObject *sip_api_convert_from_const_void_ptr(const void *val) -{ - return make_voidptr((void *)val, -1, FALSE); -} - - -/* - * Convert a sized C/C++ void pointer to a sip.voidptr object. - */ -PyObject *sip_api_convert_from_void_ptr_and_size(void *val, Py_ssize_t size) -{ - return make_voidptr(val, size, TRUE); -} - - -/* - * Convert a sized C/C++ const void pointer to a sip.voidptr object. - */ -PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val, - Py_ssize_t size) -{ - return make_voidptr((void *)val, size, FALSE); -} - - -/* - * Check that a void pointer has an explicit size and raise an exception if it - * hasn't. - */ -static int check_size(PyObject *self) -{ - if (((sipVoidPtrObject *)self)->size >= 0) - return 0; - - PyErr_SetString(PyExc_IndexError, - "sip.voidptr object has an unknown size"); - - return -1; -} - - -/* - * Check that a void pointer is writable. - */ -static int check_rw(PyObject *self) -{ - if (((sipVoidPtrObject *)self)->rw) - return 0; - - PyErr_SetString(PyExc_TypeError, - "cannot modify a read-only sip.voidptr object"); - - return -1; -} - - -/* - * Check that an index is valid for a void pointer. - */ -static int check_index(PyObject *self, Py_ssize_t idx) -{ - if (idx >= 0 && idx < ((sipVoidPtrObject *)self)->size) - return 0; - - PyErr_SetString(PyExc_IndexError, "index out of bounds"); - - return -1; -} - - -/* - * Raise an exception about a bad sub-script key. - */ -static void bad_key(PyObject *key) -{ - PyErr_Format(PyExc_TypeError, - "cannot index a sip.voidptr object using '%s'", - Py_TYPE(key)->tp_name); -} - - -/* - * Check that the size of a value is the same as the size of the slice it is - * replacing. - */ -static int check_slice_size(Py_ssize_t size, Py_ssize_t value_size) -{ - if (value_size == size) - return 0; - - PyErr_SetString(PyExc_ValueError, - "cannot modify the size of a sip.voidptr object"); - - return -1; -} - - -/* - * Do the work of converting a void pointer. - */ -static PyObject *make_voidptr(void *voidptr, Py_ssize_t size, int rw) -{ - sipVoidPtrObject *self; - - if (voidptr == NULL) - { - Py_INCREF(Py_None); - return Py_None; - } - - if ((self = PyObject_NEW(sipVoidPtrObject, &sipVoidPtr_Type)) == NULL) - return NULL; - - self->voidptr = voidptr; - self->size = size; - self->rw = rw; - - return (PyObject *)self; -} - - -/* - * Convert a Python object to the values needed to create a voidptr. - */ -static int vp_convertor(PyObject *arg, struct vp_values *vp) -{ - void *ptr; - Py_ssize_t size = -1; - int rw = TRUE; - - if (arg == Py_None) - { - ptr = NULL; - } - else if (PyCapsule_CheckExact(arg)) - { - ptr = PyCapsule_GetPointer(arg, NULL); - } - else if (PyObject_TypeCheck(arg, &sipVoidPtr_Type)) - { - ptr = ((sipVoidPtrObject *)arg)->voidptr; - size = ((sipVoidPtrObject *)arg)->size; - rw = ((sipVoidPtrObject *)arg)->rw; - } - else if (PyObject_CheckBuffer(arg)) - { - Py_buffer view; - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0) - return 0; - - ptr = view.buf; - size = view.len; - rw = !view.readonly; - - PyBuffer_Release(&view); - } - else - { - PyErr_Clear(); - ptr = PyLong_AsVoidPtr(arg); - - if (PyErr_Occurred()) - { - PyErr_SetString(PyExc_TypeError, "a single integer, Capsule, None, bytes-like object or another sip.voidptr object is required"); - return 0; - } - } - - vp->voidptr = ptr; - vp->size = size; - vp->rw = rw; - - return 1; -} - - -/* - * Get a size possibly supplied as an argument, otherwise get it from the - * object. Raise an exception if there was no size specified. - */ -static Py_ssize_t get_size_from_arg(sipVoidPtrObject *v, Py_ssize_t size) -{ - /* Use the current size if one wasn't explicitly given. */ - if (size < 0) - size = v->size; - - if (size < 0) - PyErr_SetString(PyExc_ValueError, - "a size must be given or the sip.voidptr object must have a size"); - - return size; -} diff --git a/wscript b/wscript index 4f0d0bf5..80306098 100644 --- a/wscript +++ b/wscript @@ -563,12 +563,12 @@ def build(bld): features = 'c cxx cshlib cxxshlib pyext', target = makeTargetName(bld, 'siplib'), source = ['sip/siplib/apiversions.c', - 'sip/siplib/array.c', 'sip/siplib/bool.cpp', 'sip/siplib/descriptors.c', 'sip/siplib/int_convertors.c', 'sip/siplib/objmap.c', 'sip/siplib/qtlib.c', + 'sip/siplib/sip_array.c', 'sip/siplib/siplib.c', 'sip/siplib/threads.c', 'sip/siplib/voidptr.c', diff --git a/wx/include/wxPython/sip.h b/wx/include/wxPython/sip.h deleted file mode 100644 index 5f0f0591..00000000 --- a/wx/include/wxPython/sip.h +++ /dev/null @@ -1,1909 +0,0 @@ -/* - * The SIP module interface. - * - * Copyright (c) 2020 Riverbank Computing Limited - * - * 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. - */ - - -#ifndef _SIP_H -#define _SIP_H - - -#include - -/* Sanity check on the Python version. */ -#if PY_VERSION_HEX < 0x03050000 -#error "This version of SIP requires Python v3.5 or later" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* The patch version of this implementation of the ABI. */ -#define SIP_MODULE_PATCH_VERSION 1 - - -/* - * The changes to this version of the ABI. - * - * Preserve any current exception in the wrapper tp_dealloc functions. - */ - - -/* The ABI version implemented. */ -#define SIP_ABI_MAJOR_VERSION 12 -#define SIP_ABI_MINOR_VERSION 8 - -/* The version of the code generator. */ -#define SIP_VERSION 0x50500 -#define SIP_VERSION_STR "5.5.0" - -/* These are all dependent on the user-specified name of the sip module. */ -#define _SIP_MODULE_FQ_NAME "wx.siplib" -#define _SIP_MODULE_NAME "siplib" -#define _SIP_MODULE_SHARED 1 -#define _SIP_MODULE_ENTRY PyInit_siplib -#define _SIP_MODULE_LEGACY 0 - -/* Support the historical names. */ -#define SIP_API_MAJOR_NR SIP_ABI_MAJOR_VERSION -#define SIP_API_MINOR_NR SIP_ABI_MINOR_VERSION - - -/* - * Qt includes this typedef and its meta-object system explicitly converts - * types to uint. If these correspond to signal arguments then that conversion - * is exposed. Therefore SIP generates code that uses it. This definition is - * for the cases that SIP is generating non-Qt related bindings with compilers - * that don't include it themselves (i.e. MSVC). - */ -typedef unsigned int uint; - - -/* Some C++ compatibility stuff. */ -#if defined(__cplusplus) - -/* - * Cast a PyCFunctionWithKeywords to a PyCFunction in such a way that it - * suppresses the GCC -Wcast-function-type warning. - */ -#define SIP_MLMETH_CAST(m) reinterpret_cast(reinterpret_cast(m)) - -#if __cplusplus >= 201103L || defined(_MSVC_LANG) - -/* C++11 and later. */ -#define SIP_NULLPTR nullptr -#define SIP_OVERRIDE override - -#else - -/* Earlier versions of C++. */ -#define SIP_NULLPTR NULL -#define SIP_OVERRIDE - -#endif - -#else - -/* Cast a PyCFunctionWithKeywords to a PyCFunction. */ -#define SIP_MLMETH_CAST(m) ((PyCFunction)(m)) - -/* C. */ -#define SIP_NULLPTR NULL -#define SIP_OVERRIDE - -#endif - - -/* Remove in v5.1. */ -#define SIP_SSIZE_T Py_ssize_t -#define SIP_SSIZE_T_FORMAT "%zd" -#define SIP_USE_PYCAPSULE -#define SIP_MODULE_RETURN(v) return (v) - -/* - * Remove in v5.1. These are undocumented and can be removed when PyQt5 drops - * support for Python v2. - */ -#define SIPLong_Check PyLong_Check -#define SIPLong_FromLong PyLong_FromLong -#define SIPLong_AsLong PyLong_AsLong - -#define SIPBytes_Check PyBytes_Check -#define SIPBytes_FromString PyBytes_FromString -#define SIPBytes_FromStringAndSize PyBytes_FromStringAndSize -#define SIPBytes_AsString PyBytes_AsString -#define SIPBytes_Size PyBytes_Size -#define SIPBytes_AS_STRING PyBytes_AS_STRING -#define SIPBytes_GET_SIZE PyBytes_GET_SIZE - - -/* - * The mask that can be passed to sipTrace(). - */ -#define SIP_TRACE_CATCHERS 0x0001 -#define SIP_TRACE_CTORS 0x0002 -#define SIP_TRACE_DTORS 0x0004 -#define SIP_TRACE_INITS 0x0008 -#define SIP_TRACE_DEALLOCS 0x0010 -#define SIP_TRACE_METHODS 0x0020 - - -/* - * Hide some thread dependent stuff. - */ -#ifdef WITH_THREAD -typedef PyGILState_STATE sip_gilstate_t; -#define SIP_RELEASE_GIL(gs) PyGILState_Release(gs); -#define SIP_BLOCK_THREADS {PyGILState_STATE sipGIL = PyGILState_Ensure(); -#define SIP_UNBLOCK_THREADS PyGILState_Release(sipGIL);} -#else -typedef int sip_gilstate_t; -#define SIP_RELEASE_GIL(gs) -#define SIP_BLOCK_THREADS -#define SIP_UNBLOCK_THREADS -#endif - - -/* - * Forward declarations of types. - */ -struct _sipBufferDef; -typedef struct _sipBufferDef sipBufferDef; - -struct _sipBufferInfoDef; -typedef struct _sipBufferInfoDef sipBufferInfoDef; - -struct _sipCFunctionDef; -typedef struct _sipCFunctionDef sipCFunctionDef; - -struct _sipDateDef; -typedef struct _sipDateDef sipDateDef; - -struct _sipEnumTypeObject; -typedef struct _sipEnumTypeObject sipEnumTypeObject; - -struct _sipMethodDef; -typedef struct _sipMethodDef sipMethodDef; - -struct _sipSimpleWrapper; -typedef struct _sipSimpleWrapper sipSimpleWrapper; - -struct _sipTimeDef; -typedef struct _sipTimeDef sipTimeDef; - -struct _sipTypeDef; -typedef struct _sipTypeDef sipTypeDef; - -struct _sipWrapperType; -typedef struct _sipWrapperType sipWrapperType; - -struct _sipWrapper; -typedef struct _sipWrapper sipWrapper; - - -/* - * The different events a handler can be registered for. - */ -typedef enum -{ - sipEventWrappedInstance, /* After wrapping a C/C++ instance. */ - sipEventCollectingWrapper, /* When garbage collecting a wrapper object. */ - sipEventNrEvents -} sipEventType; - -/* - * The event handlers. - */ -typedef void (*sipWrappedInstanceEventHandler)(void *sipCpp); -typedef void (*sipCollectingWrapperEventHandler)(sipSimpleWrapper *sipSelf); - - -/* - * The operation an access function is being asked to perform. - */ -typedef enum -{ - UnguardedPointer, /* Return the unguarded pointer. */ - GuardedPointer, /* Return the guarded pointer, ie. 0 if it has gone. */ - ReleaseGuard /* Release the guard, if any. */ -} AccessFuncOp; - - -/* - * Some convenient function pointers. - */ -typedef void *(*sipInitFunc)(sipSimpleWrapper *, PyObject *, PyObject *, - PyObject **, PyObject **, PyObject **); -typedef int (*sipFinalFunc)(PyObject *, void *, PyObject *, PyObject **); -typedef void *(*sipAccessFunc)(sipSimpleWrapper *, AccessFuncOp); -typedef int (*sipTraverseFunc)(void *, visitproc, void *); -typedef int (*sipClearFunc)(void *); -typedef int (*sipGetBufferFuncLimited)(PyObject *, void *, sipBufferDef *); -typedef void (*sipReleaseBufferFuncLimited)(PyObject *, void *); -#if !defined(Py_LIMITED_API) -typedef int (*sipGetBufferFunc)(PyObject *, void *, Py_buffer *, int); -typedef void (*sipReleaseBufferFunc)(PyObject *, void *, Py_buffer *); -#endif -typedef void (*sipDeallocFunc)(sipSimpleWrapper *); -typedef void *(*sipCastFunc)(void *, const sipTypeDef *); -typedef const sipTypeDef *(*sipSubClassConvertFunc)(void **); -typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *); -typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); -typedef void (*sipVirtErrorHandlerFunc)(sipSimpleWrapper *, sip_gilstate_t); -typedef int (*sipVirtHandlerFunc)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *, ...); -typedef void (*sipAssignFunc)(void *, Py_ssize_t, void *); -typedef void *(*sipArrayFunc)(Py_ssize_t); -typedef void *(*sipCopyFunc)(const void *, Py_ssize_t); -typedef void (*sipReleaseFunc)(void *, int); -typedef PyObject *(*sipPickleFunc)(void *); -typedef int (*sipAttrGetterFunc)(const sipTypeDef *, PyObject *); -typedef PyObject *(*sipVariableGetterFunc)(void *, PyObject *, PyObject *); -typedef int (*sipVariableSetterFunc)(void *, PyObject *, PyObject *); -typedef void *(*sipProxyResolverFunc)(void *); -typedef int (*sipNewUserTypeFunc)(sipWrapperType *); -typedef void (*sipWrapperVisitorFunc)(sipSimpleWrapper *, void *); - - -#if !defined(Py_LIMITED_API) -/* - * The meta-type of a wrapper type. - */ -struct _sipWrapperType { - /* - * The super-metatype. This must be first in the structure so that it can - * be cast to a PyTypeObject *. - */ - PyHeapTypeObject super; - - /* Set if the type is a user implemented Python sub-class. */ - unsigned wt_user_type : 1; - - /* Set if the type's dictionary contains all lazy attributes. */ - unsigned wt_dict_complete : 1; - - /* Unused and available for future use. */ - unsigned wt_unused : 30; - - /* The generated type structure. */ - sipTypeDef *wt_td; - - /* The list of init extenders. */ - struct _sipInitExtenderDef *wt_iextend; - - /* The handler called whenever a new user type has been created. */ - sipNewUserTypeFunc wt_new_user_type_handler; - - /* - * For the user to use. Note that any data structure will leak if the - * type is garbage collected. - */ - void *wt_user_data; -}; - - -/* - * The type of a simple C/C++ wrapper object. - */ -struct _sipSimpleWrapper { - PyObject_HEAD - - /* - * The data, initially a pointer to the C/C++ object, as interpreted by the - * access function. - */ - void *data; - - /* The optional access function. */ - sipAccessFunc access_func; - - /* Object flags. */ - unsigned sw_flags; - - /* The optional dictionary of extra references keyed by argument number. */ - PyObject *extra_refs; - - /* For the user to use. */ - PyObject *user; - - /* The instance dictionary. */ - PyObject *dict; - - /* The main instance if this is a mixin. */ - PyObject *mixin_main; - - /* Next object at this address. */ - struct _sipSimpleWrapper *next; -}; - - -/* - * The type of a C/C++ wrapper object that supports parent/child relationships. - */ -struct _sipWrapper { - /* The super-type. */ - sipSimpleWrapper super; - - /* First child object. */ - struct _sipWrapper *first_child; - - /* Next sibling. */ - struct _sipWrapper *sibling_next; - - /* Previous sibling. */ - struct _sipWrapper *sibling_prev; - - /* Owning object. */ - struct _sipWrapper *parent; -}; - - -/* - * Removed in v5.1. - * The meta-type of an enum type. (This is exposed only to support the - * deprecated sipConvertFromNamedEnum() macro.) - */ -struct _sipEnumTypeObject { - /* - * The super-metatype. This must be first in the structure so that it can - * be cast to a PyTypeObject *. - */ - PyHeapTypeObject super; - - /* The generated type structure. */ - struct _sipTypeDef *type; -}; -#endif - - -/* - * The information describing an encoded type ID. - */ -typedef struct _sipEncodedTypeDef { - /* The type number. */ - unsigned sc_type : 16; - - /* The module number (255 for this one). */ - unsigned sc_module : 8; - - /* A context specific flag. */ - unsigned sc_flag : 1; -} sipEncodedTypeDef; - - -/* - * The information describing an enum member. - */ -typedef struct _sipEnumMemberDef { - /* The member name. */ - const char *em_name; - - /* The member value. */ - int em_val; - - /* The member enum, -ve if anonymous. */ - int em_enum; -} sipEnumMemberDef; - - -/* - * The information describing static instances. - */ -typedef struct _sipInstancesDef { - /* The types. */ - struct _sipTypeInstanceDef *id_type; - - /* The void *. */ - struct _sipVoidPtrInstanceDef *id_voidp; - - /* The chars. */ - struct _sipCharInstanceDef *id_char; - - /* The strings. */ - struct _sipStringInstanceDef *id_string; - - /* The ints. */ - struct _sipIntInstanceDef *id_int; - - /* The longs. */ - struct _sipLongInstanceDef *id_long; - - /* The unsigned longs. */ - struct _sipUnsignedLongInstanceDef *id_ulong; - - /* The long longs. */ - struct _sipLongLongInstanceDef *id_llong; - - /* The unsigned long longs. */ - struct _sipUnsignedLongLongInstanceDef *id_ullong; - - /* The doubles. */ - struct _sipDoubleInstanceDef *id_double; -} sipInstancesDef; - - -/* - * The information describing a type initialiser extender. - */ -typedef struct _sipInitExtenderDef { - /* The API version range index. */ - int ie_api_range; - - /* The extender function. */ - sipInitFunc ie_extender; - - /* The class being extended. */ - sipEncodedTypeDef ie_class; - - /* The next extender for this class. */ - struct _sipInitExtenderDef *ie_next; -} sipInitExtenderDef; - - -/* - * The information describing a sub-class converter. - */ -typedef struct _sipSubClassConvertorDef { - /* The converter. */ - sipSubClassConvertFunc scc_convertor; - - /* The encoded base type. */ - sipEncodedTypeDef scc_base; - - /* The base type. */ - struct _sipTypeDef *scc_basetype; -} sipSubClassConvertorDef; - - -/* - * The structure populated by %BIGetBufferCode when the limited API is enabled. - */ -struct _sipBufferDef { - /* The address of the buffer. */ - void *bd_buffer; - - /* The length of the buffer. */ - Py_ssize_t bd_length; - - /* Set if the buffer is read-only. */ - int bd_readonly; -}; - - -/* - * The structure describing a Python buffer. - */ -struct _sipBufferInfoDef { - /* This is internal to sip. */ - void *bi_internal; - - /* The address of the buffer. */ - void *bi_buf; - - /* A reference to the object implementing the buffer interface. */ - PyObject *bi_obj; - - /* The length of the buffer in bytes. */ - Py_ssize_t bi_len; - - /* The number of dimensions. */ - int bi_ndim; - - /* The format of each element of the buffer. */ - char *bi_format; -}; - - -/* - * The structure describing a Python C function. - */ -struct _sipCFunctionDef { - /* The C function. */ - PyMethodDef *cf_function; - - /* The optional bound object. */ - PyObject *cf_self; -}; - - -/* - * The structure describing a Python method. - */ -struct _sipMethodDef { - /* The function that implements the method. */ - PyObject *pm_function; - - /* The bound object. */ - PyObject *pm_self; -}; - - -/* - * The structure describing a Python date. - */ -struct _sipDateDef { - /* The year. */ - int pd_year; - - /* The month (1-12). */ - int pd_month; - - /* The day (1-31). */ - int pd_day; -}; - - -/* - * The structure describing a Python time. - */ -struct _sipTimeDef { - /* The hour (0-23). */ - int pt_hour; - - /* The minute (0-59). */ - int pt_minute; - - /* The second (0-59). */ - int pt_second; - - /* The microsecond (0-999999). */ - int pt_microsecond; -}; - - -/* - * The different error states of handwritten code. - */ -typedef enum { - sipErrorNone, /* There is no error. */ - sipErrorFail, /* The error is a failure. */ - sipErrorContinue /* It may not apply if a later operation succeeds. */ -} sipErrorState; - - -/* - * The different Python slot types. New slots must be added to the end, - * otherwise the major version of the internal ABI must be changed. - */ -typedef enum { - str_slot, /* __str__ */ - int_slot, /* __int__ */ - float_slot, /* __float__ */ - len_slot, /* __len__ */ - contains_slot, /* __contains__ */ - add_slot, /* __add__ for number */ - concat_slot, /* __add__ for sequence types */ - sub_slot, /* __sub__ */ - mul_slot, /* __mul__ for number types */ - repeat_slot, /* __mul__ for sequence types */ - div_slot, /* __div__ */ - mod_slot, /* __mod__ */ - floordiv_slot, /* __floordiv__ */ - truediv_slot, /* __truediv__ */ - and_slot, /* __and__ */ - or_slot, /* __or__ */ - xor_slot, /* __xor__ */ - lshift_slot, /* __lshift__ */ - rshift_slot, /* __rshift__ */ - iadd_slot, /* __iadd__ for number types */ - iconcat_slot, /* __iadd__ for sequence types */ - isub_slot, /* __isub__ */ - imul_slot, /* __imul__ for number types */ - irepeat_slot, /* __imul__ for sequence types */ - idiv_slot, /* __idiv__ */ - imod_slot, /* __imod__ */ - ifloordiv_slot, /* __ifloordiv__ */ - itruediv_slot, /* __itruediv__ */ - iand_slot, /* __iand__ */ - ior_slot, /* __ior__ */ - ixor_slot, /* __ixor__ */ - ilshift_slot, /* __ilshift__ */ - irshift_slot, /* __irshift__ */ - invert_slot, /* __invert__ */ - call_slot, /* __call__ */ - getitem_slot, /* __getitem__ */ - setitem_slot, /* __setitem__ */ - delitem_slot, /* __delitem__ */ - lt_slot, /* __lt__ */ - le_slot, /* __le__ */ - eq_slot, /* __eq__ */ - ne_slot, /* __ne__ */ - gt_slot, /* __gt__ */ - ge_slot, /* __ge__ */ - bool_slot, /* __bool__, __nonzero__ */ - neg_slot, /* __neg__ */ - repr_slot, /* __repr__ */ - hash_slot, /* __hash__ */ - pos_slot, /* __pos__ */ - abs_slot, /* __abs__ */ - index_slot, /* __index__ */ - iter_slot, /* __iter__ */ - next_slot, /* __next__ */ - setattr_slot, /* __setattr__, __delattr__ */ - matmul_slot, /* __matmul__ (for Python v3.5 and later) */ - imatmul_slot, /* __imatmul__ (for Python v3.5 and later) */ - await_slot, /* __await__ (for Python v3.5 and later) */ - aiter_slot, /* __aiter__ (for Python v3.5 and later) */ - anext_slot, /* __anext__ (for Python v3.5 and later) */ -} sipPySlotType; - - -/* - * The information describing a Python slot function. - */ -typedef struct _sipPySlotDef { - /* The function. */ - void *psd_func; - - /* The type. */ - sipPySlotType psd_type; -} sipPySlotDef; - - -/* - * The information describing a Python slot extender. - */ -typedef struct _sipPySlotExtenderDef { - /* The function. */ - void *pse_func; - - /* The type. */ - sipPySlotType pse_type; - - /* The encoded class. */ - sipEncodedTypeDef pse_class; -} sipPySlotExtenderDef; - - -/* - * The information describing a typedef. - */ -typedef struct _sipTypedefDef { - /* The typedef name. */ - const char *tdd_name; - - /* The typedef value. */ - const char *tdd_type_name; -} sipTypedefDef; - - -/* - * The information describing a variable or property. - */ - -typedef enum -{ - PropertyVariable, /* A property. */ - InstanceVariable, /* An instance variable. */ - ClassVariable /* A class (i.e. static) variable. */ -} sipVariableType; - -typedef struct _sipVariableDef { - /* The type of variable. */ - sipVariableType vd_type; - - /* The name. */ - const char *vd_name; - - /* - * The getter. If this is a variable (rather than a property) then the - * actual type is sipVariableGetterFunc. - */ - PyMethodDef *vd_getter; - - /* - * The setter. If this is a variable (rather than a property) then the - * actual type is sipVariableSetterFunc. It is NULL if the property cannot - * be set or the variable is const. - */ - PyMethodDef *vd_setter; - - /* The property deleter. */ - PyMethodDef *vd_deleter; - - /* The docstring. */ - const char *vd_docstring; -} sipVariableDef; - - -/* - * The information describing a type, either a C++ class (or C struct), a C++ - * namespace, a mapped type or a named enum. - */ -struct _sipTypeDef { - /* The version range index, -1 if the type isn't versioned. */ - int td_version; - - /* The next version of this type. */ - struct _sipTypeDef *td_next_version; - - /* - * The module, 0 if the type hasn't been initialised. - */ - struct _sipExportedModuleDef *td_module; - - /* Type flags, see the sipType*() macros. */ - int td_flags; - - /* The C/C++ name of the type. */ - int td_cname; - - /* The Python type object. */ - PyTypeObject *td_py_type; - - /* Any additional fixed data generated by a plugin. */ - void *td_plugin_data; -}; - - -/* - * The information describing a container (ie. a class, namespace or a mapped - * type). - */ -typedef struct _sipContainerDef { - /* - * The Python name of the type, -1 if this is a namespace extender (in the - * context of a class) or doesn't require a namespace (in the context of a - * mapped type). */ - int cod_name; - - /* - * The scoping type or the namespace this is extending if it is a namespace - * extender. - */ - sipEncodedTypeDef cod_scope; - - /* The number of lazy methods. */ - int cod_nrmethods; - - /* The table of lazy methods. */ - PyMethodDef *cod_methods; - - /* The number of lazy enum members. */ - int cod_nrenummembers; - - /* The table of lazy enum members. */ - sipEnumMemberDef *cod_enummembers; - - /* The number of variables. */ - int cod_nrvariables; - - /* The table of variables. */ - sipVariableDef *cod_variables; - - /* The static instances. */ - sipInstancesDef cod_instances; -} sipContainerDef; - - -/* - * The information describing a C++ class (or C struct) or a C++ namespace. - */ -typedef struct _sipClassTypeDef { - /* The base type information. */ - sipTypeDef ctd_base; - - /* The container information. */ - sipContainerDef ctd_container; - - /* The docstring. */ - const char *ctd_docstring; - - /* - * The meta-type name, -1 to use the meta-type of the first super-type - * (normally sipWrapperType). - */ - int ctd_metatype; - - /* The super-type name, -1 to use sipWrapper. */ - int ctd_supertype; - - /* The super-types. */ - sipEncodedTypeDef *ctd_supers; - - /* The table of Python slots. */ - sipPySlotDef *ctd_pyslots; - - /* The initialisation function. */ - sipInitFunc ctd_init; - - /* The traverse function. */ - sipTraverseFunc ctd_traverse; - - /* The clear function. */ - sipClearFunc ctd_clear; - - /* The get buffer function. */ -#if defined(Py_LIMITED_API) - sipGetBufferFuncLimited ctd_getbuffer; -#else - sipGetBufferFunc ctd_getbuffer; -#endif - - /* The release buffer function. */ -#if defined(Py_LIMITED_API) - sipReleaseBufferFuncLimited ctd_releasebuffer; -#else - sipReleaseBufferFunc ctd_releasebuffer; -#endif - - /* The deallocation function. */ - sipDeallocFunc ctd_dealloc; - - /* The optional assignment function. */ - sipAssignFunc ctd_assign; - - /* The optional array allocation function. */ - sipArrayFunc ctd_array; - - /* The optional copy function. */ - sipCopyFunc ctd_copy; - - /* The release function, 0 if a C struct. */ - sipReleaseFunc ctd_release; - - /* The cast function, 0 if a C struct. */ - sipCastFunc ctd_cast; - - /* The optional convert to function. */ - sipConvertToFunc ctd_cto; - - /* The optional convert from function. */ - sipConvertFromFunc ctd_cfrom; - - /* The next namespace extender. */ - struct _sipClassTypeDef *ctd_nsextender; - - /* The pickle function. */ - sipPickleFunc ctd_pickle; - - /* The finalisation function. */ - sipFinalFunc ctd_final; - - /* The mixin initialisation function. */ - initproc ctd_init_mixin; -} sipClassTypeDef; - - -/* - * The information describing a mapped type. - */ -typedef struct _sipMappedTypeDef { - /* The base type information. */ - sipTypeDef mtd_base; - - /* The container information. */ - sipContainerDef mtd_container; - - /* The optional assignment function. */ - sipAssignFunc mtd_assign; - - /* The optional array allocation function. */ - sipArrayFunc mtd_array; - - /* The optional copy function. */ - sipCopyFunc mtd_copy; - - /* The optional release function. */ - sipReleaseFunc mtd_release; - - /* The convert to function. */ - sipConvertToFunc mtd_cto; - - /* The convert from function. */ - sipConvertFromFunc mtd_cfrom; -} sipMappedTypeDef; - - -/* - * The information describing a named enum. - */ -typedef struct _sipEnumTypeDef { - /* The base type information. */ - sipTypeDef etd_base; - - /* The Python name of the enum. */ - int etd_name; - - /* The scoping type, -1 if it is defined at the module level. */ - int etd_scope; - - /* The Python slots. */ - struct _sipPySlotDef *etd_pyslots; -} sipEnumTypeDef; - - -/* - * The information describing an external type. - */ -typedef struct _sipExternalTypeDef { - /* The index into the type table. */ - int et_nr; - - /* The name of the type. */ - const char *et_name; -} sipExternalTypeDef; - - -/* - * Remove in v5.1. - * The information describing a mapped class. This (and anything that uses it) - * is deprecated. - */ -typedef sipTypeDef sipMappedType; - - -/* - * Defines an entry in the module specific list of delayed dtor calls. - */ -typedef struct _sipDelayedDtor { - /* The C/C++ instance. */ - void *dd_ptr; - - /* The class name. */ - const char *dd_name; - - /* Non-zero if dd_ptr is a derived class instance. */ - int dd_isderived; - - /* Next in the list. */ - struct _sipDelayedDtor *dd_next; -} sipDelayedDtor; - - -/* - * Defines an entry in the table of global functions all of whose overloads - * are versioned (so their names can't be automatically added to the module - * dictionary). - */ -typedef struct _sipVersionedFunctionDef { - /* The name, -1 marks the end of the table. */ - int vf_name; - - /* The function itself. */ - PyCFunction vf_function; - - /* The METH_* flags. */ - int vf_flags; - - /* The docstring. */ - const char *vf_docstring; - - /* The API version range index. */ - int vf_api_range; -} sipVersionedFunctionDef; - - -/* - * Defines a virtual error handler. - */ -typedef struct _sipVirtErrorHandlerDef { - /* The name of the handler. */ - const char *veh_name; - - /* The handler function. */ - sipVirtErrorHandlerFunc veh_handler; -} sipVirtErrorHandlerDef; - - -/* - * Defines a type imported from another module. - */ -typedef union _sipImportedTypeDef { - /* The type name before the module is imported. */ - const char *it_name; - - /* The type after the module is imported. */ - sipTypeDef *it_td; -} sipImportedTypeDef; - - -/* - * Defines a virtual error handler imported from another module. - */ -typedef union _sipImportedVirtErrorHandlerDef { - /* The handler name before the module is imported. */ - const char *iveh_name; - - /* The handler after the module is imported. */ - sipVirtErrorHandlerFunc iveh_handler; -} sipImportedVirtErrorHandlerDef; - - -/* - * Defines an exception imported from another module. - */ -typedef union _sipImportedExceptionDef { - /* The exception name before the module is imported. */ - const char *iexc_name; - - /* The exception object after the module is imported. */ - PyObject *iexc_object; -} sipImportedExceptionDef; - - -/* - * The information describing an imported module. - */ -typedef struct _sipImportedModuleDef { - /* The module name. */ - const char *im_name; - - /* The types imported from the module. */ - sipImportedTypeDef *im_imported_types; - - /* The virtual error handlers imported from the module. */ - sipImportedVirtErrorHandlerDef *im_imported_veh; - - /* The exceptions imported from the module. */ - sipImportedExceptionDef *im_imported_exceptions; -} sipImportedModuleDef; - - -/* - * The main client module structure. - */ -typedef struct _sipExportedModuleDef { - /* The next in the list. */ - struct _sipExportedModuleDef *em_next; - - /* The SIP API minor version number. */ - unsigned em_api_minor; - - /* The module name. */ - int em_name; - - /* The module name as an object. */ - PyObject *em_nameobj; - - /* The string pool. */ - const char *em_strings; - - /* The imported modules. */ - sipImportedModuleDef *em_imports; - - /* The optional Qt support API. */ - struct _sipQtAPI *em_qt_api; - - /* The number of types. */ - int em_nrtypes; - - /* The table of types. */ - sipTypeDef **em_types; - - /* The table of external types. */ - sipExternalTypeDef *em_external; - - /* The number of members in global enums. */ - int em_nrenummembers; - - /* The table of members in global enums. */ - sipEnumMemberDef *em_enummembers; - - /* The number of typedefs. */ - int em_nrtypedefs; - - /* The table of typedefs. */ - sipTypedefDef *em_typedefs; - - /* The table of virtual error handlers. */ - sipVirtErrorHandlerDef *em_virterrorhandlers; - - /* The sub-class converters. */ - sipSubClassConvertorDef *em_convertors; - - /* The static instances. */ - sipInstancesDef em_instances; - - /* The license. */ - struct _sipLicenseDef *em_license; - - /* The table of exception types. */ - PyObject **em_exceptions; - - /* The table of Python slot extenders. */ - sipPySlotExtenderDef *em_slotextend; - - /* The table of initialiser extenders. */ - sipInitExtenderDef *em_initextend; - - /* The delayed dtor handler. */ - void (*em_delayeddtors)(const sipDelayedDtor *); - - /* The list of delayed dtors. */ - sipDelayedDtor *em_ddlist; - - /* - * The array of API version definitions. Each definition takes up 3 - * elements. If the third element of a 3-tuple is negative then the first - * two elements define an API and its default version. All such - * definitions will appear at the end of the array. If the first element - * of a 3-tuple is negative then that is the last element of the array. - */ - int *em_versions; - - /* The optional table of versioned functions. */ - sipVersionedFunctionDef *em_versioned_functions; -} sipExportedModuleDef; - - -/* - * The information describing a license to be added to a dictionary. - */ -typedef struct _sipLicenseDef { - /* The type of license. */ - const char *lc_type; - - /* The licensee. */ - const char *lc_licensee; - - /* The timestamp. */ - const char *lc_timestamp; - - /* The signature. */ - const char *lc_signature; -} sipLicenseDef; - - -/* - * The information describing a void pointer instance to be added to a - * dictionary. - */ -typedef struct _sipVoidPtrInstanceDef { - /* The void pointer name. */ - const char *vi_name; - - /* The void pointer value. */ - void *vi_val; -} sipVoidPtrInstanceDef; - - -/* - * The information describing a char instance to be added to a dictionary. - */ -typedef struct _sipCharInstanceDef { - /* The char name. */ - const char *ci_name; - - /* The char value. */ - char ci_val; - - /* The encoding used, either 'A', 'L', '8' or 'N'. */ - char ci_encoding; -} sipCharInstanceDef; - - -/* - * The information describing a string instance to be added to a dictionary. - * This is also used as a hack to add (or fix) other types rather than add a - * new table type and so requiring a new major version of the API. - */ -typedef struct _sipStringInstanceDef { - /* The string name. */ - const char *si_name; - - /* The string value. */ - const char *si_val; - - /* - * The encoding used, either 'A', 'L', '8' or 'N'. 'w' and 'W' are also - * used to support the fix for wchar_t. - */ - char si_encoding; -} sipStringInstanceDef; - - -/* - * The information describing an int instance to be added to a dictionary. - */ -typedef struct _sipIntInstanceDef { - /* The int name. */ - const char *ii_name; - - /* The int value. */ - int ii_val; -} sipIntInstanceDef; - - -/* - * The information describing a long instance to be added to a dictionary. - */ -typedef struct _sipLongInstanceDef { - /* The long name. */ - const char *li_name; - - /* The long value. */ - long li_val; -} sipLongInstanceDef; - - -/* - * The information describing an unsigned long instance to be added to a - * dictionary. - */ -typedef struct _sipUnsignedLongInstanceDef { - /* The unsigned long name. */ - const char *uli_name; - - /* The unsigned long value. */ - unsigned long uli_val; -} sipUnsignedLongInstanceDef; - - -/* - * The information describing a long long instance to be added to a dictionary. - */ -typedef struct _sipLongLongInstanceDef { - /* The long long name. */ - const char *lli_name; - - /* The long long value. */ -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG lli_val; -#else - long lli_val; -#endif -} sipLongLongInstanceDef; - - -/* - * The information describing an unsigned long long instance to be added to a - * dictionary. - */ -typedef struct _sipUnsignedLongLongInstanceDef { - /* The unsigned long long name. */ - const char *ulli_name; - - /* The unsigned long long value. */ -#if defined(HAVE_LONG_LONG) - unsigned PY_LONG_LONG ulli_val; -#else - unsigned long ulli_val; -#endif -} sipUnsignedLongLongInstanceDef; - - -/* - * The information describing a double instance to be added to a dictionary. - */ -typedef struct _sipDoubleInstanceDef { - /* The double name. */ - const char *di_name; - - /* The double value. */ - double di_val; -} sipDoubleInstanceDef; - - -/* - * The information describing a class or enum instance to be added to a - * dictionary. - */ -typedef struct _sipTypeInstanceDef { - /* The type instance name. */ - const char *ti_name; - - /* The actual instance. */ - void *ti_ptr; - - /* A pointer to the generated type. */ - struct _sipTypeDef **ti_type; - - /* The wrapping flags. */ - int ti_flags; -} sipTypeInstanceDef; - - -/* - * Remove in v5.1. - * Define a mapping between a wrapped type identified by a string and the - * corresponding Python type. - */ -typedef struct _sipStringTypeClassMap { - /* The type as a string. */ - const char *typeString; - - /* A pointer to the Python type. */ - struct _sipWrapperType **pyType; -} sipStringTypeClassMap; - - -/* - * Remove in v5.1. - * Define a mapping between a wrapped type identified by an integer and the - * corresponding Python type. - */ -typedef struct _sipIntTypeClassMap { - /* The type as an integer. */ - int typeInt; - - /* A pointer to the Python type. */ - struct _sipWrapperType **pyType; -} sipIntTypeClassMap; - - -/* - * A Python method's component parts. This allows us to re-create the method - * without changing the reference counts of the components. - */ -typedef struct _sipPyMethod { - /* The function. */ - PyObject *mfunc; - - /* Self if it is a bound method. */ - PyObject *mself; -} sipPyMethod; - - -/* - * A slot (in the Qt, rather than Python, sense). - */ -typedef struct _sipSlot { - /* Name if a Qt or Python signal. */ - char *name; - - /* Signal or Qt slot object. */ - PyObject *pyobj; - - /* Python slot method, pyobj is NULL. */ - sipPyMethod meth; - - /* A weak reference to the slot, Py_True if pyobj has an extra reference. */ - PyObject *weakSlot; -} sipSlot; - - -/* - * The API exported by the SIP module, ie. pointers to all the data and - * functions that can be used by generated code. - */ -typedef struct _sipAPIDef { - /* - * This must be the first entry and it's signature must not change so that - * version number mismatches can be detected and reported. - */ - int (*api_export_module)(sipExportedModuleDef *client, unsigned api_major, - unsigned api_minor, void *unused); - - /* - * The following are part of the public API. - */ - PyTypeObject *api_simplewrapper_type; - PyTypeObject *api_wrapper_type; - PyTypeObject *api_wrappertype_type; - PyTypeObject *api_voidptr_type; - - void (*api_bad_catcher_result)(PyObject *method); - void (*api_bad_length_for_slice)(Py_ssize_t seqlen, Py_ssize_t slicelen); - PyObject *(*api_build_result)(int *isErr, const char *fmt, ...); - PyObject *(*api_call_method)(int *isErr, PyObject *method, const char *fmt, - ...); - void (*api_call_procedure_method)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *, const char *, ...); - PyObject *(*api_connect_rx)(PyObject *txObj, const char *sig, - PyObject *rxObj, const char *slot, int type); - Py_ssize_t (*api_convert_from_sequence_index)(Py_ssize_t idx, - Py_ssize_t len); - int (*api_can_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - int flags); - void *(*api_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp); - void *(*api_force_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, - PyObject *transferObj, int flags, int *statep, int *iserrp); - - /* - * The following are deprecated parts of the public API. - */ - int (*api_can_convert_to_enum)(PyObject *pyObj, const sipTypeDef *td); - - /* - * The following are part of the public API. - */ - void (*api_release_type)(void *cpp, const sipTypeDef *td, int state); - PyObject *(*api_convert_from_type)(void *cpp, const sipTypeDef *td, - PyObject *transferObj); - PyObject *(*api_convert_from_new_type)(void *cpp, const sipTypeDef *td, - PyObject *transferObj); - PyObject *(*api_convert_from_enum)(int eval, const sipTypeDef *td); - int (*api_get_state)(PyObject *transferObj); - PyObject *(*api_disconnect_rx)(PyObject *txObj, const char *sig, - PyObject *rxObj, const char *slot); - void (*api_free)(void *mem); - PyObject *(*api_get_pyobject)(void *cppPtr, const sipTypeDef *td); - void *(*api_malloc)(size_t nbytes); - int (*api_parse_result)(int *isErr, PyObject *method, PyObject *res, - const char *fmt, ...); - void (*api_trace)(unsigned mask, const char *fmt, ...); - void (*api_transfer_back)(PyObject *self); - void (*api_transfer_to)(PyObject *self, PyObject *owner); - void (*api_transfer_break)(PyObject *self); - unsigned long (*api_long_as_unsigned_long)(PyObject *o); - PyObject *(*api_convert_from_void_ptr)(void *val); - PyObject *(*api_convert_from_const_void_ptr)(const void *val); - PyObject *(*api_convert_from_void_ptr_and_size)(void *val, - Py_ssize_t size); - PyObject *(*api_convert_from_const_void_ptr_and_size)(const void *val, - Py_ssize_t size); - void *(*api_convert_to_void_ptr)(PyObject *obj); - int (*api_export_symbol)(const char *name, void *sym); - void *(*api_import_symbol)(const char *name); - const sipTypeDef *(*api_find_type)(const char *type); - int (*api_register_py_type)(PyTypeObject *type); - const sipTypeDef *(*api_type_from_py_type_object)(PyTypeObject *py_type); - const sipTypeDef *(*api_type_scope)(const sipTypeDef *td); - const char *(*api_resolve_typedef)(const char *name); - int (*api_register_attribute_getter)(const sipTypeDef *td, - sipAttrGetterFunc getter); - int (*api_is_api_enabled)(const char *name, int from, int to); - sipErrorState (*api_bad_callable_arg)(int arg_nr, PyObject *arg); - void *(*api_get_address)(struct _sipSimpleWrapper *w); - void (*api_set_destroy_on_exit)(int); - int (*api_enable_autoconversion)(const sipTypeDef *td, int enable); - void *(*api_get_mixin_address)(struct _sipSimpleWrapper *w, - const sipTypeDef *td); - PyObject *(*api_convert_from_new_pytype)(void *cpp, PyTypeObject *py_type, - sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...); - PyObject *(*api_convert_to_typed_array)(void *data, const sipTypeDef *td, - const char *format, size_t stride, Py_ssize_t len, int flags); - PyObject *(*api_convert_to_array)(void *data, const char *format, - Py_ssize_t len, int flags); - int (*api_register_proxy_resolver)(const sipTypeDef *td, - sipProxyResolverFunc resolver); - PyInterpreterState *(*api_get_interpreter)(void); - sipNewUserTypeFunc (*api_set_new_user_type_handler)(const sipTypeDef *, - sipNewUserTypeFunc); - void (*api_set_type_user_data)(sipWrapperType *, void *); - void *(*api_get_type_user_data)(const sipWrapperType *); - PyObject *(*api_py_type_dict)(const PyTypeObject *); - const char *(*api_py_type_name)(const PyTypeObject *); - int (*api_get_method)(PyObject *, sipMethodDef *); - PyObject *(*api_from_method)(const sipMethodDef *); - int (*api_get_c_function)(PyObject *, sipCFunctionDef *); - int (*api_get_date)(PyObject *, sipDateDef *); - PyObject *(*api_from_date)(const sipDateDef *); - int (*api_get_datetime)(PyObject *, sipDateDef *, sipTimeDef *); - PyObject *(*api_from_datetime)(const sipDateDef *, const sipTimeDef *); - int (*api_get_time)(PyObject *, sipTimeDef *); - PyObject *(*api_from_time)(const sipTimeDef *); - int (*api_is_user_type)(const sipWrapperType *); - struct _frame *(*api_get_frame)(int); - int (*api_check_plugin_for_type)(const sipTypeDef *, const char *); - PyObject *(*api_unicode_new)(Py_ssize_t, unsigned, int *, void **); - void (*api_unicode_write)(int, void *, int, unsigned); - void *(*api_unicode_data)(PyObject *, int *, Py_ssize_t *); - int (*api_get_buffer_info)(PyObject *, sipBufferInfoDef *); - void (*api_release_buffer_info)(sipBufferInfoDef *); - PyObject *(*api_get_user_object)(const sipSimpleWrapper *); - void (*api_set_user_object)(sipSimpleWrapper *, PyObject *); - - /* - * The following are not part of the public API. - */ - int (*api_init_module)(sipExportedModuleDef *client, PyObject *mod_dict); - int (*api_parse_args)(PyObject **parseErrp, PyObject *sipArgs, - const char *fmt, ...); - int (*api_parse_pair)(PyObject **parseErrp, PyObject *arg0, PyObject *arg1, - const char *fmt, ...); - - /* - * The following are part of the public API. - */ - void (*api_instance_destroyed)(sipSimpleWrapper *sipSelf); - - /* - * The following are not part of the public API. - */ - void (*api_no_function)(PyObject *parseErr, const char *func, - const char *doc); - void (*api_no_method)(PyObject *parseErr, const char *scope, - const char *method, const char *doc); - void (*api_abstract_method)(const char *classname, const char *method); - void (*api_bad_class)(const char *classname); - void *(*api_get_cpp_ptr)(sipSimpleWrapper *w, const sipTypeDef *td); - void *(*api_get_complex_cpp_ptr)(sipSimpleWrapper *w); - PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper *sipSelf, const char *cname, const char *mname); - void (*api_call_hook)(const char *hookname); - void (*api_end_thread)(void); - void (*api_raise_unknown_exception)(void); - void (*api_raise_type_exception)(const sipTypeDef *td, void *ptr); - int (*api_add_type_instance)(PyObject *dict, const char *name, - void *cppPtr, const sipTypeDef *td); - void (*api_bad_operator_arg)(PyObject *self, PyObject *arg, - sipPySlotType st); - PyObject *(*api_pyslot_extend)(sipExportedModuleDef *mod, sipPySlotType st, - const sipTypeDef *type, PyObject *arg0, PyObject *arg1); - void (*api_add_delayed_dtor)(sipSimpleWrapper *w); - char (*api_bytes_as_char)(PyObject *obj); - const char *(*api_bytes_as_string)(PyObject *obj); - char (*api_string_as_ascii_char)(PyObject *obj); - const char *(*api_string_as_ascii_string)(PyObject **obj); - char (*api_string_as_latin1_char)(PyObject *obj); - const char *(*api_string_as_latin1_string)(PyObject **obj); - char (*api_string_as_utf8_char)(PyObject *obj); - const char *(*api_string_as_utf8_string)(PyObject **obj); -#if defined(HAVE_WCHAR_H) - wchar_t (*api_unicode_as_wchar)(PyObject *obj); - wchar_t *(*api_unicode_as_wstring)(PyObject *obj); -#else - int (*api_unicode_as_wchar)(PyObject *obj); - int *(*api_unicode_as_wstring)(PyObject *obj); -#endif - int (*api_deprecated)(const char *classname, const char *method); - void (*api_keep_reference)(PyObject *self, int key, PyObject *obj); - int (*api_parse_kwd_args)(PyObject **parseErrp, PyObject *sipArgs, - PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, - const char *fmt, ...); - void (*api_add_exception)(sipErrorState es, PyObject **parseErrp); - int (*api_parse_result_ex)(sip_gilstate_t, sipVirtErrorHandlerFunc, - sipSimpleWrapper *, PyObject *method, PyObject *res, - const char *fmt, ...); - void (*api_call_error_handler)(sipVirtErrorHandlerFunc, - sipSimpleWrapper *, sip_gilstate_t); - int (*api_init_mixin)(PyObject *self, PyObject *args, PyObject *kwds, - const sipClassTypeDef *ctd); - PyObject *(*api_get_reference)(PyObject *self, int key); - - /* - * The following are part of the public API. - */ - int (*api_is_owned_by_python)(sipSimpleWrapper *); - - /* - * The following are not part of the public API. - */ - int (*api_is_derived_class)(sipSimpleWrapper *); - - /* - * The following may be used by Qt support code but no other handwritten - * code. - */ - void (*api_free_sipslot)(sipSlot *slot); - int (*api_same_slot)(const sipSlot *sp, PyObject *rxObj, const char *slot); - void *(*api_convert_rx)(sipWrapper *txSelf, const char *sigargs, - PyObject *rxObj, const char *slot, const char **memberp, - int flags); - PyObject *(*api_invoke_slot)(const sipSlot *slot, PyObject *sigargs); - PyObject *(*api_invoke_slot_ex)(const sipSlot *slot, PyObject *sigargs, - int check_receiver); - int (*api_save_slot)(sipSlot *sp, PyObject *rxObj, const char *slot); - void (*api_clear_any_slot_reference)(sipSlot *slot); - int (*api_visit_slot)(sipSlot *slot, visitproc visit, void *arg); - - /* - * The following are deprecated parts of the public API. - */ - PyTypeObject *(*api_find_named_enum)(const char *type); - const sipMappedType *(*api_find_mapped_type)(const char *type); - sipWrapperType *(*api_find_class)(const char *type); - sipWrapperType *(*api_map_int_to_class)(int typeInt, - const sipIntTypeClassMap *map, int maplen); - sipWrapperType *(*api_map_string_to_class)(const char *typeString, - const sipStringTypeClassMap *map, int maplen); - - /* - * The following are part of the public API. - */ - int (*api_enable_gc)(int enable); - void (*api_print_object)(PyObject *o); - int (*api_register_event_handler)(sipEventType type, const sipTypeDef *td, - void *handler); - int (*api_convert_to_enum)(PyObject *obj, const sipTypeDef *td); - int (*api_convert_to_bool)(PyObject *obj); - int (*api_enable_overflow_checking)(int enable); - char (*api_long_as_char)(PyObject *o); - signed char (*api_long_as_signed_char)(PyObject *o); - unsigned char (*api_long_as_unsigned_char)(PyObject *o); - short (*api_long_as_short)(PyObject *o); - unsigned short (*api_long_as_unsigned_short)(PyObject *o); - int (*api_long_as_int)(PyObject *o); - unsigned int (*api_long_as_unsigned_int)(PyObject *o); - long (*api_long_as_long)(PyObject *o); -#if defined(HAVE_LONG_LONG) - PY_LONG_LONG (*api_long_as_long_long)(PyObject *o); - unsigned PY_LONG_LONG (*api_long_as_unsigned_long_long)(PyObject *o); -#else - void *api_long_as_long_long; - void *api_long_as_unsigned_long_long; -#endif - - /* - * The following are not part of the public API. - */ - void (*api_instance_destroyed_ex)(sipSimpleWrapper **sipSelfp); - - /* - * The following are part of the public API. - */ - int (*api_convert_from_slice_object)(PyObject *slice, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, - Py_ssize_t *slicelength); - size_t (*api_long_as_size_t)(PyObject *o); - void (*api_visit_wrappers)(sipWrapperVisitorFunc visitor, void *closure); - int (*api_register_exit_notifier)(PyMethodDef *md); - - /* - * The following are not part of the public API. - */ - PyObject *(*api_is_py_method_12_8)(sip_gilstate_t *gil, char *pymc, - sipSimpleWrapper **sipSelfp, const char *cname, const char *mname); -} sipAPIDef; - -const sipAPIDef *sip_init_library(PyObject *mod_dict); - - -/* - * The API implementing the optional Qt support. - */ -typedef struct _sipQtAPI { - sipTypeDef **qt_qobject; - void *(*qt_create_universal_signal)(void *, const char **); - void *(*qt_find_universal_signal)(void *, const char **); - void *(*qt_create_universal_slot)(struct _sipWrapper *, const char *, - PyObject *, const char *, const char **, int); - void (*qt_destroy_universal_slot)(void *); - void *(*qt_find_slot)(void *, const char *, PyObject *, const char *, - const char **); - int (*qt_connect)(void *, const char *, void *, const char *, int); - int (*qt_disconnect)(void *, const char *, void *, const char *); - int (*qt_same_name)(const char *, const char *); - sipSlot *(*qt_find_sipslot)(void *, void **); - int (*qt_emit_signal)(PyObject *, const char *, PyObject *); - int (*qt_connect_py_signal)(PyObject *, const char *, PyObject *, - const char *); - void (*qt_disconnect_py_signal)(PyObject *, const char *, PyObject *, - const char *); -} sipQtAPI; - - -/* - * These are flags that can be passed to sipCanConvertToType(), - * sipConvertToType() and sipForceConvertToType(). - */ -#define SIP_NOT_NONE 0x01 /* Disallow None. */ -#define SIP_NO_CONVERTORS 0x02 /* Disable any type converters. */ - - -/* - * These are flags that can be passed to sipConvertToArray(). These are held - * in sw_flags. - */ -#define SIP_READ_ONLY 0x01 /* The array is read-only. */ -#define SIP_OWNS_MEMORY 0x02 /* The array owns its memory. */ - - -/* - * These are the state flags returned by %ConvertToTypeCode. Note that the - * values share the same "flagspace" as the contents of sw_flags. - */ -#define SIP_TEMPORARY 0x01 /* A temporary instance. */ -#define SIP_DERIVED_CLASS 0x02 /* The instance is derived. */ - - -/* - * These flags are specific to the Qt support API. - */ -#define SIP_SINGLE_SHOT 0x01 /* The connection is single shot. */ - - -/* - * Useful macros, not part of the public API. - */ - -/* These are held in sw_flags. */ -#define SIP_INDIRECT 0x0004 /* If there is a level of indirection. */ -#define SIP_ACCFUNC 0x0008 /* If there is an access function. */ -#define SIP_NOT_IN_MAP 0x0010 /* If Python object is not in the map. */ - -#if !defined(Py_LIMITED_API) -#define SIP_PY_OWNED 0x0020 /* If owned by Python. */ -#define SIP_SHARE_MAP 0x0040 /* If the map slot might be occupied. */ -#define SIP_CPP_HAS_REF 0x0080 /* If C/C++ has a reference. */ -#define SIP_POSSIBLE_PROXY 0x0100 /* If there might be a proxy slot. */ -#define SIP_ALIAS 0x0200 /* If it is an alias. */ -#define SIP_CREATED 0x0400 /* If the C/C++ object has been created. */ - -#define sipIsDerived(sw) ((sw)->sw_flags & SIP_DERIVED_CLASS) -#define sipIsIndirect(sw) ((sw)->sw_flags & SIP_INDIRECT) -#define sipIsAccessFunc(sw) ((sw)->sw_flags & SIP_ACCFUNC) -#define sipNotInMap(sw) ((sw)->sw_flags & SIP_NOT_IN_MAP) -#define sipSetNotInMap(sw) ((sw)->sw_flags |= SIP_NOT_IN_MAP) -#define sipIsPyOwned(sw) ((sw)->sw_flags & SIP_PY_OWNED) -#define sipSetPyOwned(sw) ((sw)->sw_flags |= SIP_PY_OWNED) -#define sipResetPyOwned(sw) ((sw)->sw_flags &= ~SIP_PY_OWNED) -#define sipCppHasRef(sw) ((sw)->sw_flags & SIP_CPP_HAS_REF) -#define sipSetCppHasRef(sw) ((sw)->sw_flags |= SIP_CPP_HAS_REF) -#define sipResetCppHasRef(sw) ((sw)->sw_flags &= ~SIP_CPP_HAS_REF) -#define sipPossibleProxy(sw) ((sw)->sw_flags & SIP_POSSIBLE_PROXY) -#define sipSetPossibleProxy(sw) ((sw)->sw_flags |= SIP_POSSIBLE_PROXY) -#define sipIsAlias(sw) ((sw)->sw_flags & SIP_ALIAS) -#define sipWasCreated(sw) ((sw)->sw_flags & SIP_CREATED) -#endif - -#define SIP_TYPE_TYPE_MASK 0x0007 /* The type type mask. */ -#define SIP_TYPE_CLASS 0x0000 /* If the type is a C++ class. */ -#define SIP_TYPE_NAMESPACE 0x0001 /* If the type is a C++ namespace. */ -#define SIP_TYPE_MAPPED 0x0002 /* If the type is a mapped type. */ -#define SIP_TYPE_ENUM 0x0003 /* If the type is a named enum. */ -#define SIP_TYPE_SCOPED_ENUM 0x0004 /* If the type is a scoped enum. */ -#define SIP_TYPE_ABSTRACT 0x0008 /* If the type is abstract. */ -#define SIP_TYPE_SCC 0x0010 /* If the type is subject to sub-class converters. */ -#define SIP_TYPE_ALLOW_NONE 0x0020 /* If the type can handle None. */ -#define SIP_TYPE_STUB 0x0040 /* If the type is a stub. */ -#define SIP_TYPE_NONLAZY 0x0080 /* If the type has a non-lazy method. */ -#define SIP_TYPE_SUPER_INIT 0x0100 /* If the instance's super init should be called. */ -#define SIP_TYPE_LIMITED_API 0x0200 /* Use the limited API. If this is more generally required it may need to be moved to the module definition. */ - - -/* - * The following are part of the public API. - */ -#define sipTypeIsClass(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_CLASS) -#define sipTypeIsNamespace(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_NAMESPACE) -#define sipTypeIsMapped(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_MAPPED) -#define sipTypeIsEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_ENUM) -#define sipTypeIsScopedEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_SCOPED_ENUM) -#define sipTypeAsPyTypeObject(td) ((td)->td_py_type) -#define sipTypeName(td) sipNameFromPool((td)->td_module, (td)->td_cname) -#define sipTypePluginData(td) ((td)->td_plugin_data) - - -/* - * Remove in v5.1. - */ -#define sipClassName(w) PyString_FromString(Py_TYPE(w)->tp_name) -#define sipIsExactWrappedType(wt) (sipTypeAsPyTypeObject((wt)->wt_td) == (PyTypeObject *)(wt)) - - -/* - * The following are not part of the public API. - */ -#define sipTypeIsAbstract(td) ((td)->td_flags & SIP_TYPE_ABSTRACT) -#define sipTypeHasSCC(td) ((td)->td_flags & SIP_TYPE_SCC) -#define sipTypeAllowNone(td) ((td)->td_flags & SIP_TYPE_ALLOW_NONE) -#define sipTypeIsStub(td) ((td)->td_flags & SIP_TYPE_STUB) -#define sipTypeSetStub(td) ((td)->td_flags |= SIP_TYPE_STUB) -#define sipTypeHasNonlazyMethod(td) ((td)->td_flags & SIP_TYPE_NONLAZY) -#define sipTypeCallSuperInit(td) ((td)->td_flags & SIP_TYPE_SUPER_INIT) -#define sipTypeUseLimitedAPI(td) ((td)->td_flags & SIP_TYPE_LIMITED_API) - -/* - * Get various names from the string pool for various data types. - */ -#define sipNameFromPool(em, mr) (&((em)->em_strings)[(mr)]) -#define sipNameOfModule(em) sipNameFromPool((em), (em)->em_name) -#define sipPyNameOfContainer(cod, td) sipNameFromPool((td)->td_module, (cod)->cod_name) -#define sipPyNameOfEnum(etd) sipNameFromPool((etd)->etd_base.td_module, (etd)->etd_name) - - -/* - * The following are PyQt4-specific extensions. In SIP v5 they will be pushed - * out to a plugin supplied by PyQt4. - */ - -/* - * The description of a Qt signal for PyQt4. - */ -typedef struct _pyqt4QtSignal { - /* The C++ name and signature of the signal. */ - const char *signature; - - /* The optional docstring. */ - const char *docstring; - - /* - * If the signal is an overload of regular methods then this points to the - * code that implements those methods. - */ - PyMethodDef *non_signals; - - /* - * The hack to apply when built against Qt5: - * - * 0 - no hack - * 1 - add an optional None - * 2 - add an optional [] - * 3 - add an optional False - */ - int hack; -} pyqt4QtSignal; - - -/* - * This is the PyQt4-specific extension to the generated class type structure. - */ -typedef struct _pyqt4ClassPluginDef { - /* A pointer to the QObject sub-class's staticMetaObject class variable. */ - const void *static_metaobject; - - /* - * A set of flags. At the moment only bit 0 is used to say if the type is - * derived from QFlags. - */ - unsigned flags; - - /* - * The table of signals emitted by the type. These are grouped by signal - * name. - */ - const pyqt4QtSignal *qt_signals; -} pyqt4ClassPluginDef; - - -/* - * The following are PyQt5-specific extensions. In SIP v5 they will be pushed - * out to a plugin supplied by PyQt5. - */ - -/* - * The description of a Qt signal for PyQt5. - */ -typedef int (*pyqt5EmitFunc)(void *, PyObject *); - -typedef struct _pyqt5QtSignal { - /* The normalised C++ name and signature of the signal. */ - const char *signature; - - /* The optional docstring. */ - const char *docstring; - - /* - * If the signal is an overload of regular methods then this points to the - * code that implements those methods. - */ - PyMethodDef *non_signals; - - /* - * If the signal has optional arguments then this function will implement - * emit() for the signal. - */ - pyqt5EmitFunc emitter; -} pyqt5QtSignal; - - -/* - * This is the PyQt5-specific extension to the generated class type structure. - */ -typedef struct _pyqt5ClassPluginDef { - /* A pointer to the QObject sub-class's staticMetaObject class variable. */ - const void *static_metaobject; - - /* - * A set of flags. At the moment only bit 0 is used to say if the type is - * derived from QFlags. - */ - unsigned flags; - - /* - * The table of signals emitted by the type. These are grouped by signal - * name. - */ - const pyqt5QtSignal *qt_signals; - - /* The name of the interface that the class defines. */ - const char *qt_interface; -} pyqt5ClassPluginDef; - - -#ifdef __cplusplus -} -#endif - - -#endif