1

I am trying to make a simple extension in C that should be able to extend python code . I found that code on https://github.com/munirhossain/py_c_extension

#include <Python.h> // Function 1: A simple 'hello world' function static PyObject* helloworld(PyObject* self, PyObject* args) { printf("Hello Munir\n"); Py_RETURN_NONE; return Py_None; } // Function 2: A C fibonacci implementation // this is nothing special and looks exactly // like a normal C version of fibonacci would look int Cfib(int n) { if (n < 2) return n; else return Cfib(n-1)+Cfib(n-2); } // Our Python binding to our C function // This will take one and only one non-keyword argument static PyObject* fib(PyObject* self, PyObject* args) { // instantiate our `n` value int n; // if our `n` value if(!PyArg_ParseTuple(args, "i", &n)) return NULL; // return our computed fib number return Py_BuildValue("i", Cfib(n)); } // Our Module's Function Definition struct // We require this `NULL` to signal the end of our method // definition static PyMethodDef myMethods[] = { { "helloworld", helloworld, METH_NOARGS, "Prints Hello Munir" }, { "fib", fib, METH_VARARGS, "Computes Fibonacci" }, { NULL, NULL, 0, NULL } }; // Our Module Definition struct static struct PyModuleDef myModule = { PyModuleDef_HEAD_INIT, "myModule", "Test Module", -1, myMethods }; // Initializes our module using our above struct PyMODINIT_FUNC PyInit_myModule(void) { return PyModule_Create(&myModule); } 

I would like to modify that code like when I call the helloworld func , like helloworld("max") it returns Hello max in C , but idk how can I use PyObject* args :/ Any ideas how I can do that (in C) ?

1 Answer 1

1

You should read the PyArg_ParseTuple documentation. Basically this should work:

static PyObject* helloworld(PyObject* self, PyObject* args) { const char *name; if (!PyArg_ParseTuple(args, "s", &name)) { return NULL; } printf("Hello %s\n", name); Py_RETURN_NONE; } 

and you need to change the method definition in the table to

{ "helloworld", helloworld, METH_VARARGS, "Prints Hello <name>" }, 

naturally, as it now takes arguments. The description s says that the argument tuple must contain exactly one item and it should be of type str; it is converted to UTF-8 (each CPython string object can contain a cached copy of the string content in UTF-8 for C use), and a pointer to the first character is stored into the pointer object pointed to by the corresponding argument in the variable argument list (i.e. the &name - the output value is const char *, and the corresponding argument must be a pointer to such an object, i.e. const char **).

If PyArg_ParseTuple returns a falsy value, it means the conversion failed and a Python exception has been set. We raise the exception on Python side by returning NULL instead of Py_None from the function.

Lastly,

return Py_None; 

is not correct - you must always increment the reference counter on any such value before returning it - that's what Py_RETURN_NONE macro does in it - it is functionally equivalent to

Py_INCREF(Py_None); return Py_None; 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.