1

I am following this doc on extending c++ to python. As far as what was demonstrated there, the PyObject *spam_system(PyObject *self, PyObject *args) {...} works fine when passing to array of PyModuleDef but if I want to add more args to spam_system, it results in an invaid conversation following

error: invalid conversion from ‘PyObject* (*)()’ {aka ‘_object* (*)()’} to ‘PyCFunction’ {aka ‘_object* (*)(_object*, _object*)’} [-fpermissive]

for more example, I want to define a method that takes no args, and returns a PyLong_FromLong from long/int

PyObject test() {return PyLong_FromLong(1);}

static PyMethodDef SpamMethods[] = {
    {"system",  spam_system, METH_VARARGS,
     "Execute a shell command."},
    {"test",  test , METH_NOARGS,
              //^ the error happens here 
     "test."},

   {NULL, NULL, 0, NULL}        /* Sentinel */
};

How can I define a method that takes no args or more than two args? (adding two args to test works fine).

PatXio
  • 129
  • 2
  • 16
  • You just have to force conversion to PyCFunction pointer. Write `{"test", (PyCFunction)test , METH_NOARGS, "test."}` – Arty Feb 18 '21 at 18:36
  • wouldn't this have any consequences? – PatXio Feb 18 '21 at 19:10
  • No, it is totally alright. That is what documentation says to do. I've being reading documentation regarding programming under C++ and found this and was also surprised, but in fact it worked. Also on the very first run you'll notice if it works or not. If it doesn't work then program will just crash because of corrupted stack (wrong function type corrupts stack in half of time), if it doesn't crash then it definitely will work correctly. – Arty Feb 19 '21 at 08:10
  • All alright, def need to try, What I'm even more curious about is why does `test` remain `PyObject *` as long as there are two instances of `PyObject*` being passed and then becomes `PyCFunction` if num of args is <=/>= 2? – PatXio Feb 19 '21 at 09:15

1 Answers1

1

Since it's C++, which is more strict about function pointer casting than C, you'll have to cast to (PyCFunction), or, IIRC, (void*) also works.

tekknolagi
  • 10,663
  • 24
  • 75
  • 119