Finding python function parameters from C++
I am calling python functions from C++. I was wondering if it is possible to determine the number of parameters and the names of these parameters. I have read the link How to find the number of parameters to a Python function from C? however I do not really understand.
I have this C++ function that calls the function 'add' from pyFunction.py. 'add' takes two parameters and returns the sum.
static float CallPythonFunc( float *parameters )
{
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pArgs;
float ret;
// Initialize the python interpreter
Py_Initialize();
// Make sure we are getting the module from the correct place
// ### This is where we will put the path input
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"/Developer/IsadoraSDK/IsadoraDemoMathFunction/\")");
// Build the name object
// ### This is where we will put the function input
pName = PyString_FromString("pyFunction");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is a borrowed reference
pFunc = PyDict_GetItemString(pDict, "add");
//
// Somehow get the number of arguments and possible the arguments names from 'add'
//
if (PyCallable_Check(pFunc))
{
// Set the number of arguments
// This is where I would like to pass in number of arguments
pArgs = PyTuple_New( 2 /*number of arguments*/ );
//
// Instead of the following if I had the arguments I could loop through them
// and pass the correct number in
//
// Argument 1
pValue = PyFloat_FromDouble((double)parameters[0]);
PyTuple_SetItem(pArgs, 0, pValue);
// Argument 2
pValue = PyFloat_FromDouble((double)parameters[1]);
PyTuple_SetItem(pArgs, 1, pValue);
// Make the call to the function
pValue = PyObject_CallObject(pFunc, pArgs);
// Set return value
ret = (float)PyFloat_AsDouble(pValue);
// Clean up
Py_DECREF(pArgs);
Py_DECREF(pValue);
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return ret;
}
I am really not that familiar with C/C++ so any help would be really helpful. Thanks to everyone for their time!
EDIT: So something like the following?
PyObject *tuple, *arglist;
tuple = PyObject_CallMethod(pFunc,"inspect.getargspec","add");
arglist = P开发者_JAVA百科yTuple_GetItem(tuple,0);
int size = PyObject_Size(arglist);
This answer to the question you linked to seems to be what you want. inspect.getargspec
does exactly what you want on the Python side, and as the answer states, you can use PyObject_CallMethod or one of the related functions described at that link target to call inspect.getargspec
from your C++ code, get the returned tuple as a PyObject
, use PyTuple_GetItem(returned_tuple, 0)
to get the argument list, and then use either PyObject_Size()
or PyObject_Length()
on the list to get the number of arguments. You'll also want to check the second and third elements of the returned tuple and increment the number of arguments by 1 for each of the two that is not Py_None
. See the below code snippet for why.
>>> import inspect
>>> def testfunc(a, b, c, *d, **e):
pass
>>> inspect.getargspec(testfunc)
ArgSpec(args=['a', 'b', 'c'], varargs='d', keywords='e', defaults=None)
Here's an example of what you should do (not all possible errors may be checked for, but it should be all of the NULL checks that may be necessary):
PyObject *pName, *pInspect, *argspec_tuple, *arglist;
int size;
pName = PyString_FromString("inspect");
if (pName)
{
pInspect = PyImport_Import(pName);
Py_DECREF(pName);
if (pInspect)
{
pName = PyString_FromString("getargspec");
if (pName)
{
argspec_tuple = PyObject_CallMethodObjArgs(pInspect, pName, pFunc, NULL);
Py_DECREF(pName);
if (argspec_tuple)
{
arglist = PyTuple_GetItem(argspec_tuple, 0);
if (arglist)
{
size = PyObject_Size(arglist)
+ (PyTuple_GetItem(argspec_tuple, 1) == Py_None ? 0 : 1)
+ (PyTuple_GetItem(argspec_tuple, 2) == Py_None ? 0 : 1); // Haven't actually tested this, but it should work
}
}
}
}
}
精彩评论