From b948b0cd3e86f5d2ad6e57e49588659f50c0a47f Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Tue, 5 Nov 2024 19:17:00 +0100 Subject: [PATCH] Move python dict wrapper outside of impl in order to avoid name collision. --- source/loaders/py_loader/CMakeLists.txt | 2 + .../include/py_loader/py_loader_dict.h | 42 +++++ .../include/py_loader/py_loader_impl.h | 2 - .../loaders/py_loader/source/py_loader_dict.c | 172 ++++++++++++++++++ .../loaders/py_loader/source/py_loader_impl.c | 146 +-------------- .../loaders/py_loader/source/py_loader_port.c | 1 + 6 files changed, 219 insertions(+), 146 deletions(-) create mode 100644 source/loaders/py_loader/include/py_loader/py_loader_dict.h create mode 100644 source/loaders/py_loader/source/py_loader_dict.c diff --git a/source/loaders/py_loader/CMakeLists.txt b/source/loaders/py_loader/CMakeLists.txt index 2b8153e5d..eed3658bc 100644 --- a/source/loaders/py_loader/CMakeLists.txt +++ b/source/loaders/py_loader/CMakeLists.txt @@ -88,6 +88,7 @@ set(headers ${include_path}/py_loader_impl.h ${include_path}/py_loader_port.h ${include_path}/py_loader_threading.h + ${include_path}/py_loader_dict.h ) set(sources @@ -95,6 +96,7 @@ set(sources ${source_path}/py_loader_impl.c ${source_path}/py_loader_port.c ${source_path}/py_loader_threading.cpp + ${source_path}/py_loader_dict.c ) # Group source files diff --git a/source/loaders/py_loader/include/py_loader/py_loader_dict.h b/source/loaders/py_loader/include/py_loader/py_loader_dict.h new file mode 100644 index 000000000..f1cc908a9 --- /dev/null +++ b/source/loaders/py_loader/include/py_loader/py_loader_dict.h @@ -0,0 +1,42 @@ +/* + * Loader Library by Parra Studios + * A plugin for loading python code at run-time into a process. + * + * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef PY_LOADER_DICT_H +#define PY_LOADER_DICT_H 1 + +#include + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +PY_LOADER_NO_EXPORT int py_loader_impl_dict_type_init(void); + +PY_LOADER_NO_EXPORT PyObject *py_loader_impl_finalizer_wrap_map(PyObject *obj, void *v); + +#ifdef __cplusplus +} +#endif + +#endif /* PY_LOADER_DICT_H */ diff --git a/source/loaders/py_loader/include/py_loader/py_loader_impl.h b/source/loaders/py_loader/include/py_loader/py_loader_impl.h index 7da3504a9..7ec76f33a 100644 --- a/source/loaders/py_loader/include/py_loader/py_loader_impl.h +++ b/source/loaders/py_loader/include/py_loader/py_loader_impl.h @@ -58,8 +58,6 @@ PY_LOADER_NO_EXPORT value py_loader_impl_capi_to_value(loader_impl impl, PyObjec PY_LOADER_NO_EXPORT PyObject *py_loader_impl_value_to_capi(loader_impl impl, type_id id, value v); -PY_LOADER_NO_EXPORT PyObject *py_loader_impl_finalizer_wrap_map(PyObject *obj, value v); - PY_LOADER_NO_EXPORT int py_loader_impl_finalizer_object(loader_impl impl, PyObject *obj, value v); #ifdef __cplusplus diff --git a/source/loaders/py_loader/source/py_loader_dict.c b/source/loaders/py_loader/source/py_loader_dict.c new file mode 100644 index 000000000..e68531ff4 --- /dev/null +++ b/source/loaders/py_loader/source/py_loader_dict.c @@ -0,0 +1,172 @@ +/* + * Loader Library by Parra Studios + * A plugin for loading python code at run-time into a process. + * + * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include + +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE + #endif + #include +#endif + +struct py_loader_impl_dict_obj +{ + PyDictObject dict; + value v; + PyObject *parent; +}; + +static void py_loader_impl_dict_dealloc(struct py_loader_impl_dict_obj *self); + +static PyObject *py_loader_impl_dict_sizeof(struct py_loader_impl_dict_obj *self, void *unused); + +static int py_loader_impl_dict_init(struct py_loader_impl_dict_obj *self, PyObject *args, PyObject *kwds); + +static struct PyMethodDef py_loader_impl_dict_methods[] = { + { "__sizeof__", (PyCFunction)py_loader_impl_dict_sizeof, METH_NOARGS, PyDoc_STR("Get size of dictionary.") }, + { NULL, NULL, 0, NULL } +}; + +union py_loader_impl_dict_cast +{ + PyTypeObject *type_object; + PyObject *object; +}; + +static PyTypeObject py_loader_impl_dict_type = { + PyVarObject_HEAD_INIT(NULL, 0) "DictWrapper", + sizeof(struct py_loader_impl_dict_obj), + 0, + (destructor)py_loader_impl_dict_dealloc, /* tp_dealloc */ + 0, /* tp_vectorcall_offset */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + PyDoc_STR("Dict wrapper destructor hook"), /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + py_loader_impl_dict_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 */ + (initproc)py_loader_impl_dict_init, /* 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 */ + 0, /* tp_vectorcall */ +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12 + 0, /* tp_watched */ +#endif +#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13 + 0, /* tp_versions_used */ +#endif +}; + +PyObject *py_loader_impl_dict_sizeof(struct py_loader_impl_dict_obj *self, void *Py_UNUSED(unused)) +{ + Py_ssize_t res; + + res = _PyDict_SizeOf((PyDictObject *)self); + res += sizeof(struct py_loader_impl_dict_obj) - sizeof(PyDictObject); + return PyLong_FromSsize_t(res); +} + +int py_loader_impl_dict_init(struct py_loader_impl_dict_obj *self, PyObject *args, PyObject *kwds) +{ + if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0) + return -1; + self->v = NULL; + return 0; +} + +void py_loader_impl_dict_dealloc(struct py_loader_impl_dict_obj *self) +{ + value_type_destroy(self->v); + Py_DECREF(self->parent); /* TODO: Review if this is correct or this line is unnecessary */ + + PyDict_Type.tp_dealloc((PyObject *)self); +} + +int py_loader_impl_dict_type_init() +{ + /* py_loader_impl_dict_type is derived from PyDict_Type */ + py_loader_impl_dict_type.tp_base = &PyDict_Type; + + return PyType_Ready(&py_loader_impl_dict_type); +} + +PyObject *py_loader_impl_finalizer_wrap_map(PyObject *obj, void *v) +{ + py_loader_thread_acquire(); + + PyObject *args = PyTuple_New(1); + union py_loader_impl_dict_cast dict_cast = { &py_loader_impl_dict_type }; + + PyTuple_SetItem(args, 0, obj); + Py_INCREF(obj); + PyObject *wrapper = PyObject_CallObject(dict_cast.object, args); + Py_DECREF(args); + + py_loader_thread_release(); + + if (wrapper == NULL) + { + return NULL; + } + + struct py_loader_impl_dict_obj *wrapper_obj = (struct py_loader_impl_dict_obj *)wrapper; + + wrapper_obj->v = v; + wrapper_obj->parent = obj; + + return wrapper; +} diff --git a/source/loaders/py_loader/source/py_loader_impl.c b/source/loaders/py_loader/source/py_loader_impl.c index cd804cb69..556ba0aa8 100644 --- a/source/loaders/py_loader/source/py_loader_impl.c +++ b/source/loaders/py_loader/source/py_loader_impl.c @@ -18,6 +18,7 @@ * */ +#include #include #include #include @@ -45,13 +46,6 @@ #include -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13 - #ifndef Py_BUILD_CORE - #define Py_BUILD_CORE - #endif - #include -#endif - #define PY_LOADER_IMPL_FUNCTION_TYPE_INVOKE_FUNC "__py_loader_impl_function_type_invoke__" #define PY_LOADER_IMPL_FINALIZER_FUNC "__py_loader_impl_finalizer__" @@ -220,87 +214,6 @@ static PyMethodDef py_loader_impl_finalizer_defs[] = { { NULL, NULL, 0, NULL } }; -struct py_loader_impl_dict_obj -{ - PyDictObject dict; - value v; - PyObject *parent; -}; - -static void py_loader_impl_dict_dealloc(struct py_loader_impl_dict_obj *self); - -static PyObject *py_loader_impl_dict_sizeof(struct py_loader_impl_dict_obj *self, void *unused); - -static int py_loader_impl_dict_init(struct py_loader_impl_dict_obj *self, PyObject *args, PyObject *kwds); - -static struct PyMethodDef py_loader_impl_dict_methods[] = { - { "__sizeof__", (PyCFunction)py_loader_impl_dict_sizeof, METH_NOARGS, PyDoc_STR("Get size of dictionary.") }, - { NULL, NULL, 0, NULL } -}; - -union py_loader_impl_dict_cast -{ - PyTypeObject *type_object; - PyObject *object; -}; - -static PyTypeObject py_loader_impl_dict_type = { - PyVarObject_HEAD_INIT(NULL, 0) "DictWrapper", - sizeof(struct py_loader_impl_dict_obj), - 0, - (destructor)py_loader_impl_dict_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("Dict wrapper destructor hook"), /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - py_loader_impl_dict_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 */ - (initproc)py_loader_impl_dict_init, /* 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 */ - 0, /* tp_vectorcall */ -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12 - 0, /* tp_watched */ -#endif -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13 - 0, /* tp_versions_used */ -#endif -}; - /* Implements: if __name__ == "__main__": */ static int py_loader_impl_run_main = 1; static char *py_loader_impl_main_module = NULL; @@ -308,23 +221,6 @@ static char *py_loader_impl_main_module = NULL; /* Holds reference to the original PyCFunction.tp_dealloc method */ static void (*py_loader_impl_pycfunction_dealloc)(PyObject *) = NULL; -PyObject *py_loader_impl_dict_sizeof(struct py_loader_impl_dict_obj *self, void *Py_UNUSED(unused)) -{ - Py_ssize_t res; - - res = _PyDict_SizeOf((PyDictObject *)self); - res += sizeof(struct py_loader_impl_dict_obj) - sizeof(PyDictObject); - return PyLong_FromSsize_t(res); -} - -int py_loader_impl_dict_init(struct py_loader_impl_dict_obj *self, PyObject *args, PyObject *kwds) -{ - if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0) - return -1; - self->v = NULL; - return 0; -} - PyObject *py_loader_impl_finalizer_object_impl(PyObject *self, PyObject *Py_UNUSED(args)) { value v = PyCapsule_GetPointer(self, NULL); @@ -340,41 +236,6 @@ PyObject *py_loader_impl_finalizer_object_impl(PyObject *self, PyObject *Py_UNUS Py_RETURN_NONE; } -void py_loader_impl_dict_dealloc(struct py_loader_impl_dict_obj *self) -{ - value_type_destroy(self->v); - Py_DECREF(self->parent); /* TODO: Review if this is correct or this line is unnecessary */ - - PyDict_Type.tp_dealloc((PyObject *)self); -} - -PyObject *py_loader_impl_finalizer_wrap_map(PyObject *obj, value v) -{ - py_loader_thread_acquire(); - - PyObject *args = PyTuple_New(1); - union py_loader_impl_dict_cast dict_cast = { &py_loader_impl_dict_type }; - - PyTuple_SetItem(args, 0, obj); - Py_INCREF(obj); - PyObject *wrapper = PyObject_CallObject(dict_cast.object, args); - Py_DECREF(args); - - py_loader_thread_release(); - - if (wrapper == NULL) - { - return NULL; - } - - struct py_loader_impl_dict_obj *wrapper_obj = (struct py_loader_impl_dict_obj *)wrapper; - - wrapper_obj->v = v; - wrapper_obj->parent = obj; - - return wrapper; -} - int py_loader_impl_finalizer_object(loader_impl impl, PyObject *obj, value v) { py_loader_thread_acquire(); @@ -2838,10 +2699,7 @@ loader_impl_data py_loader_impl_initialize(loader_impl impl, configuration confi goto error_after_thread_background_module; } - /* py_loader_impl_dict_type is derived from PyDict_Type */ - py_loader_impl_dict_type.tp_base = &PyDict_Type; - - if (PyType_Ready(&py_loader_impl_dict_type) < 0) + if (py_loader_impl_dict_type_init() < 0) { goto error_after_asyncio_module; } diff --git a/source/loaders/py_loader/source/py_loader_port.c b/source/loaders/py_loader/source/py_loader_port.c index fad849e4b..136635c31 100644 --- a/source/loaders/py_loader/source/py_loader_port.c +++ b/source/loaders/py_loader/source/py_loader_port.c @@ -20,6 +20,7 @@ #include +#include #include #include #include