Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,70 @@ PyObject* CPyCppyy::CPPMethod::GetSignature(bool fa)
return CPyCppyy_PyText_FromString(GetSignatureString(fa).c_str());
}

/**
* @brief Returns a tuple with the names of the input parameters of this method.
*
* For example given a function with prototype:
*
* double foo(int a, float b, double c)
*
* this function returns:
*
* ('a', 'b', 'c')
*/
PyObject *CPyCppyy::CPPMethod::GetSignatureNames()
{
// Build a tuple of the argument names for this signature.
int argcount = GetMaxArgs();
PyObject *signature_names = PyTuple_New(argcount);

for (int iarg = 0; iarg < argcount; ++iarg) {
const std::string &argname_cpp = Cppyy::GetMethodArgName(fMethod, iarg);
PyObject *argname_py = CPyCppyy_PyText_FromString(argname_cpp.c_str());
PyTuple_SET_ITEM(signature_names, iarg, argname_py);
}

return signature_names;
}

/**
* @brief Returns a dictionary with the types of the signature of this method.
*
* This dictionary will store both the return type and the input parameter
* types of this method, respectively with keys "return_type" and
* "input_types", for example given a function with prototype:
*
* double foo(int a, float b, double c)
*
* this function returns:
*
* {'input_types': ('int', 'float', 'double'), 'return_type': 'double'}
*/
PyObject *CPyCppyy::CPPMethod::GetSignatureTypes()
{

PyObject *signature_types_dict = PyDict_New();

// Insert the return type first
std::string return_type = GetReturnTypeName();
PyObject *return_type_py = CPyCppyy_PyText_FromString(return_type.c_str());
PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("return_type"), return_type_py);

// Build a tuple of the argument types for this signature.
int argcount = GetMaxArgs();
PyObject *parameter_types = PyTuple_New(argcount);

for (int iarg = 0; iarg < argcount; ++iarg) {
const std::string &argtype_cpp = Cppyy::GetMethodArgType(fMethod, iarg);
PyObject *argtype_py = CPyCppyy_PyText_FromString(argtype_cpp.c_str());
PyTuple_SET_ITEM(parameter_types, iarg, argtype_py);
}

PyDict_SetItem(signature_types_dict, CPyCppyy_PyText_FromString("input_types"), parameter_types);

return signature_types_dict;
}

//----------------------------------------------------------------------------
std::string CPyCppyy::CPPMethod::GetReturnTypeName()
{
Expand Down
2 changes: 2 additions & 0 deletions bindings/pyroot/cppyy/CPyCppyy/src/CPPMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class CPPMethod : public PyCallable {

public:
PyObject* GetSignature(bool show_formalargs = true) override;
PyObject* GetSignatureNames() override;
PyObject* GetSignatureTypes() override;
PyObject* GetPrototype(bool show_formalargs = true) override;
PyObject* GetTypeName() override;
PyObject* Reflex(Cppyy::Reflex::RequestId_t request,
Expand Down
58 changes: 57 additions & 1 deletion bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ class TPythonCallback : public PyCallable {
PyObject* GetSignature(bool /*show_formalargs*/ = true) override {
return CPyCppyy_PyText_FromString("*args, **kwargs");
}
PyObject* GetSignatureNames() override {
return PyTuple_New(0);
}
PyObject* GetSignatureTypes() override {
return PyTuple_New(0);
}
PyObject* GetPrototype(bool /*show_formalargs*/ = true) override {
return CPyCppyy_PyText_FromString("<callback>");
}
Expand Down Expand Up @@ -285,6 +291,54 @@ static int mp_doc_set(CPPOverload* pymeth, PyObject *val, void *)
return 0;
}

/**
* @brief Returns a dictionary with the input parameter names for all overloads.
*
* This dictionary may look like:
*
* {'double ::foo(int a, float b, double c)': ('a', 'b', 'c'),
* 'float ::foo(float b)': ('b',),
* 'int ::foo(int a)': ('a',),
* 'int ::foo(int a, float b)': ('a', 'b')}
*/
static PyObject *mp_func_overloads_names(CPPOverload *pymeth)
{

const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;

PyObject *overloads_names_dict = PyDict_New();

for (PyCallable *method : methods) {
PyDict_SetItem(overloads_names_dict, method->GetPrototype(), method->GetSignatureNames());
}

return overloads_names_dict;
}

/**
* @brief Returns a dictionary with the types of all overloads.
*
* This dictionary may look like:
*
* {'double ::foo(int a, float b, double c)': {'input_types': ('int', 'float', 'double'), 'return_type': 'double'},
* 'float ::foo(float b)': {'input_types': ('float',), 'return_type': 'float'},
* 'int ::foo(int a)': {'input_types': ('int',), 'return_type': 'int'},
* 'int ::foo(int a, float b)': {'input_types': ('int', 'float'), 'return_type': 'int'}}
*/
static PyObject *mp_func_overloads_types(CPPOverload *pymeth)
{

const CPPOverload::Methods_t &methods = pymeth->fMethodInfo->fMethods;

PyObject *overloads_types_dict = PyDict_New();

for (PyCallable *method : methods) {
PyDict_SetItem(overloads_types_dict, method->GetPrototype(), method->GetSignatureTypes());
}

return overloads_types_dict;
}

//----------------------------------------------------------------------------
static PyObject* mp_meth_func(CPPOverload* pymeth, void*)
{
Expand Down Expand Up @@ -582,6 +636,8 @@ static PyGetSetDef mp_getset[] = {
{(char*)"func_globals", (getter)mp_func_globals, nullptr, nullptr, nullptr},
{(char*)"func_doc", (getter)mp_doc, (setter)mp_doc_set, nullptr, nullptr},
{(char*)"func_name", (getter)mp_name, nullptr, nullptr, nullptr},
{(char*)"func_overloads_types", (getter)mp_func_overloads_types, nullptr, nullptr, nullptr},
{(char*)"func_overloads_names", (getter)mp_func_overloads_names, nullptr, nullptr, nullptr},


// flags to control behavior
Expand Down Expand Up @@ -1250,4 +1306,4 @@ CPyCppyy::CPPOverload::MethodInfo_t::~MethodInfo_t()
Py_XDECREF(fDoc);
}

// TODO: something like PyMethod_Fini to clear up the free_list
// TODO: something like PyMethod_Fini to clear up the free_list
2 changes: 2 additions & 0 deletions bindings/pyroot/cppyy/CPyCppyy/src/PyCallable.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class PyCallable {

public:
virtual PyObject* GetSignature(bool show_formalargs = true) = 0;
virtual PyObject* GetSignatureNames() = 0;
virtual PyObject* GetSignatureTypes() = 0;
virtual PyObject* GetPrototype(bool show_formalargs = true) = 0;
virtual PyObject* GetTypeName() { return GetPrototype(false); }
virtual PyObject* GetDocString() { return GetPrototype(); }
Expand Down
Loading
Loading