Using my routines as functions AND methods

Guenther Sohler guenther.sohler at gmail.com
Thu Jan 4 02:38:28 EST 2024


Thank you for your answers.
apparently I did not express myself clear enough. Let me rephrase.

I got an embedded  C function like this:

==
PyObject *python_translate(PyObject *self, PyObject *args, PyObject *kwargs)
{
  char *kwlist[] = {"obj", "v", NULL};
  PyObject *v = NULL;
  PyObject *obj = NULL;
  double x = 0, y = 0, z = 0;
  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist,
                                   &obj,
                                   &v
                                   )) {
    PyErr_SetString(PyExc_TypeError, "Error during parsing
translate(object,vec3)");
    return NULL;
  }
...

PyMethodDef PyOpenSCADFunctions[] = {
  {"translate", (PyCFunction) python_translate, METH_VARARGS |
METH_KEYWORDS, "Move  Object."},
 ...

static PyModuleDef OpenSCADModule = {
  PyModuleDef_HEAD_INIT,
  "openscad",
  "OpenSCAD Python Module",
  -1,
  PyOpenSCADFunctions,
...
};

============
>From within python i can successfully use it with

translate(my_object, [2,0,0])

my_object is an instance of embedded class PyOpenSCADType, so alternatively
I want to use my function as method too, like so:

my_object.translate([2,0,0])

WITHOUT duplicating the code for python_translate

So the idea is to call the translate-function from within the translate
method and insert "self" into the args tuple.
However my solution somewhat works but is not very stable and quite prone
to crash.

Which are my alertnatives ?


On Wed, Jan 3, 2024 at 11:47 PM Guenther Sohler <guenther.sohler at gmail.com>
wrote:

> Hi,
>
> In my cpython i have written quite some functions to modify "objects".
> and their python syntax is e.g.\
>
> translate(obj, vec). e.g whereas obj is ALWAYS first argument.
>
> on c side this functions looks like:
> PyObject *python_translate(PyObject *self, PyObject *args, PyObject
> *kwargs)
>
> this works great when specifying a list of functions in PyModuleDef
> structure.
>
> However, I also want to use these functions as class methods without
> having to
> write the function , twice. When using the SAME function as a methos, the
> args tuple must insert/contain "self" in the first location, so i have
> written a function to do that:
>
> PyObject *python_oo_args(PyObject *self, PyObject *args) // returns new
> reference,
> {
>   int i;
>   PyObject *item;
>   int n = PyTuple_Size(args);
>   PyObject *new_args = PyTuple_New(n + 1);
>   PyTuple_SetItem(new_args, 0, self);
>
>   for (i = 0; i < PyTuple_Size(args); i++) {
>     item = PyTuple_GetItem(args, i);
>     PyTuple_SetItem(new_args, i + 1, item);
>   }
>   return new_args;
> }
>
> To fill in method array, i have created a #define like this:
>
> #define OO_METHOD_ENTRY(name,desc) \
>   { #name, (PyCFunction) ( [ ] (PyObject *self, PyObject *args) ->
> PyObject * { \
>   PyObject *new_args = python_oo_args(self, args); \
>   PyObject *result = python_##name(self, new_args, NULL); \
>   return result;  } ),  METH_VARARGS | METH_KEYWORDS, (desc)},
>
> (this uses a lambda function)
>
> and use this in the array as:
>
> PyMethodDef PyOpenSCADMethods[] = {
>   OO_METHOD_ENTRY(translate,"Move Object")
>   OO_METHOD_ENTRY(right,"Right Object")
>
> Using this  i can reuse all the functions as methods,
> but its not 100% stable/bulletproof and crashes sometimes.
> So there is the bug ?
> Is there a better approach to reach my goal ?
>
>
> thank you
>
>


More information about the Python-list mailing list