Skip to content

Commit

Permalink
Move python dict wrapper outside of impl in order to avoid name colli…
Browse files Browse the repository at this point in the history
…sion.
  • Loading branch information
viferga committed Nov 5, 2024
1 parent f93ddb2 commit b948b0c
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 146 deletions.
2 changes: 2 additions & 0 deletions source/loaders/py_loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ 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
${source_path}/py_loader.c
${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
Expand Down
42 changes: 42 additions & 0 deletions source/loaders/py_loader/include/py_loader/py_loader_dict.h
Original file line number Diff line number Diff line change
@@ -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 <vic798@gmail.com>
*
* 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 <py_loader/py_loader_api.h>

#include <loader/loader_impl_interface.h>

#include <Python.h>

#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 */
2 changes: 0 additions & 2 deletions source/loaders/py_loader/include/py_loader/py_loader_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
172 changes: 172 additions & 0 deletions source/loaders/py_loader/source/py_loader_dict.c
Original file line number Diff line number Diff line change
@@ -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 <vic798@gmail.com>
*
* 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 <py_loader/py_loader_dict.h>
#include <py_loader/py_loader_threading.h>

#include <Python.h>

#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13
#ifndef Py_BUILD_CORE
#define Py_BUILD_CORE
#endif
#include <internal/pycore_dict.h>
#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;
}
Loading

0 comments on commit b948b0c

Please sign in to comment.