tags:

views:

133

answers:

3

I'm using the Python C API to call Python functions from my application. I'd like to present a list of functions that could be called and would like to be able to limit this list to just the ones with the expected number of parameters.

I'm happy that I can walk the dictionary to extract a list of functions and use PyCallable_Check to find out if they're callable, but I'm not sure how I can find out how many parameters each function is expecting?

I've found one technique involving Boost::Python, but would rather not add that for what (I hope!) will be a minor addition.

Thanks :)

+1  A: 

Maybe this is helpful? (not tested, there could be relevant pieces of information along this thread)...

ChristopheD
Am upvoting since there were indeed relevant pieces of information :)
Peter
A: 

Your C code can call inspect.getargspec just like any Python code would (e.g. via PyObject_CallMethod or other equivalent ways) and get all the scoop about the signature of each function or other callable that it may care about.

Alex Martelli
+2  A: 

Okay, so in the end I've discovered how to do it. User-defined Python functions have a member called func_code (in Python 3.0+ it's __code__), which itself has a member co_argcount, which is presumably what Boost::Python extracts in the example given by Christophe.

The code I'm using looks like this (it's heavily based on a documentation example of how to walk a Python dictionary):

   PyObject *key, *value;
   int pos = 0;
   while(PyDict_Next(pyDictionary, &pos, &key, &value)) {
      if(PyCallable_Check(value)) {
         PyObject* fc = PyObject_GetAttrString(value, "func_code");
         if(fc) {
            PyObject* ac = PyObject_GetAttrString(fc, "co_argcount");
            if(ac) {
               const int count = PyInt_AsLong(ac);
               // we now have the argument count, do something with this function
               Py_DECREF(ac);
            }
            Py_DECREF(fc);
         }
      }
   }

Thanks anyway - that thread did indeed lead me in the right direction :)

Peter