0

I am trying to pass a python object from python to a C module without converting it, but I get a weird error. I copied most of the code from an example in the python documentation and only changed the spam_system method in spammodule.cpp. I am using python 3.11 I am obviously missing something and any help would be greatly appreciated.

spammodule.cpp:

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <bits/stdc++.h>

static PyObject* spam_system(PyObject *self, PyObject *args)
{
    PyObject *command;
// Parsing arguments and building values documentation: https://docs.python.org/3/c-api/arg.html#other-objects
    if (!PyArg_ParseTuple(args, "0", &command)) {
        std::cout << "Something went wrong\n";
        return NULL;
    }
    return PyLong_FromLong(0);
}
//The rest is copied from the documentation
static PyMethodDef SpamMethods[] = {
    {"system",  spam_system, METH_VARARGS,
     "Execute a shell command."},
};

static struct PyModuleDef spammodule = {
    PyModuleDef_HEAD_INIT,
    "spam",
    PyDoc_STR("calls with system"),
    -1,
    SpamMethods
};

PyMODINIT_FUNC PyInit_spam(void)
{
    return PyModule_Create(&spammodule);
}

int main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
        fprintf(stderr, "Error: could not extend in-built modules table\n");
        exit(1);
    }
    Py_SetProgramName(program);
    Py_Initialize();
    PyObject *pmodule = PyImport_ImportModule("spam");
    if (!pmodule) {
        PyErr_Print();
        fprintf(stderr, "Error: could not import module 'spam'\n");
    }
    PyMem_RawFree(program);
    return 0;
}

setup.py:

from setuptools import Extension, setup
setup(
    ext_modules=[
        Extension(
            name="spam",
            sources=["spammodule.cpp"],
        ),
    ]
)

main.py:

import spam
spam.system("foo")

output:

Something went wrong
Traceback (most recent call last):
  File "/home/tamas/Documents/Metro/test.py", line 2, in <module>
    spam.system("asdf")
TypeError: function takes exactly 0 arguments (1 given)

I also tried to call spam.system with no arguments, and got the following error:

Something went wrong
Traceback (most recent call last):
  File "/home/tamas/Documents/Metro/test.py", line 2, in <module>
    spam.system()
SystemError: bad format string: 0

This seems to make sense.

I also tried passing other objects(int, function, etc.) but got the same results.

I found a similar thread which wasn't answered from 7.5 years ago: Python C Extension issue: "TypeError: function takes exactly 0 arguments (1 given)"

Thank you in advance for your answers

Matiiss
  • 5,970
  • 2
  • 12
  • 29
  • Also if the function only accepts a single object as an argument, you can use `METH_O` flag and the second argument to the function would be the object: https://docs.python.org/3/c-api/structures.html?highlight=meth_noargs#METH_O – Matiiss Jan 23 '23 at 14:05
  • 1
    You should use `O(Capital letter)` as format to parse the argument as PyObject. `PyArg_ParseTuple(args, "O", &command)` – Abdul Niyas P M Jan 23 '23 at 14:06

0 Answers0