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) ?

asked Jan 16, 2021 at 16:33

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;
answered Jan 16, 2021 at 17:14
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.