Allow calling of C++ methods from python
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Testing passed
|
Commit Message
Currently it's not possible to call C++ methods from python.
Using this example:
```
class B
{
static int static_func ();
int arg0_func ();
int arg1_func (int arg1);
int arg2_func (int arg1, int arg2);
};
B *b_obj = new B;
```
Trying to call B::static_func gives this error:
```
(gdb) py b_obj = gdb.parse_and_eval('b_obj')
(gdb) py print(b_obj['static_func']())
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
Error while executing Python code.
```
TYPE_CODE_METHOD was simply missing as a possible type in
valpy_call, now the same is possible:
```
(gdb) py b_obj = gdb.parse_and_eval('b_obj')
(gdb) py print(b_obj['static_func']())
1111
```
Note that it's necessary to explicitely add the this pointer
as the first argument in a call of non-static methods:
```
(gdb) py print(b_obj['arg0_func']())
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: Too few arguments in function call.
Error while executing Python code.
(gdb) py print(b_obj['arg0_func'](b_obj))
198
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13326
---
gdb/python/py-value.c | 5 +++--
gdb/testsuite/gdb.python/py-value-cc.cc | 25 ++++++++++++++++++++++++
gdb/testsuite/gdb.python/py-value-cc.exp | 12 ++++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
Comments
>>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
Hannes> static int static_func ();
Hannes> (gdb) py b_obj = gdb.parse_and_eval('b_obj')
Hannes> (gdb) py print(b_obj['static_func']())
Hannes> Traceback (most recent call last):
Hannes> File "<string>", line 1, in <module>
Hannes> RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
I'm a bit surprised that a static method is not TYPE_CODE_FUNC.
It seems like it should be, because these are really just functions.
Hannes> (gdb) py print(b_obj['arg0_func']())
Hannes> Traceback (most recent call last):
Hannes> File "<string>", line 1, in <module>
Hannes> gdb.error: Too few arguments in function call.
Hannes> Error while executing Python code.
Hannes> (gdb) py print(b_obj['arg0_func'](b_obj))
Hannes> 198
How does this interact with overloading?
It seems to me that either b_obj['name'] has to return some kind of
overload set, or we need a different API, like b_obj.call_method('name', ...).
In the latter case we could have it automatically supply 'this', at
least when it's needed.
Tom
Am Samstag, 16. Dezember 2023, 01:30:31 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
>
> Hannes> static int static_func ();
>
> Hannes> (gdb) py b_obj = gdb.parse_and_eval('b_obj')
> Hannes> (gdb) py print(b_obj['static_func']())
> Hannes> Traceback (most recent call last):
> Hannes> File "<string>", line 1, in <module>
> Hannes> RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
>
> I'm a bit surprised that a static method is not TYPE_CODE_FUNC.
> It seems like it should be, because these are really just functions.
I never really questioned it being TYPE_CODE_METHOD, I was just wondering
instead if there is a flag that tells us that it is a static method.
> Hannes> (gdb) py print(b_obj['arg0_func']())
> Hannes> Traceback (most recent call last):
> Hannes> File "<string>", line 1, in <module>
> Hannes> gdb.error: Too few arguments in function call.
> Hannes> Error while executing Python code.
> Hannes> (gdb) py print(b_obj['arg0_func'](b_obj))
> Hannes> 198
>
> How does this interact with overloading?
Probably as you expected, it doesn't work, since the [] operator
of gdb.Value doesn't know what to do:
(gdb) py print(b_obj['overloaded_func'])
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: cannot resolve overloaded method `overloaded_func': no arguments supplied
Error while executing Python code.
> It seems to me that either b_obj['name'] has to return some kind of
> overload set, or we need a different API, like b_obj.call_method('name', ...).
>
> In the latter case we could have it automatically supply 'this', at
> least when it's needed.
The overload set would probably be relatively easy to implement, while
the call_method would be easier to use, if it automatically chooses the
right one based on the arguments.
Regards
Hannes
Ping.
Am Samstag, 16. Dezember 2023, 12:40:25 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
> Am Samstag, 16. Dezember 2023, 01:30:31 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
>
> > >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
> >
> > Hannes> static int static_func ();
> >
> > Hannes> (gdb) py b_obj = gdb.parse_and_eval('b_obj')
> > Hannes> (gdb) py print(b_obj['static_func']())
> > Hannes> Traceback (most recent call last):
> > Hannes> File "<string>", line 1, in <module>
> > Hannes> RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
> >
> > I'm a bit surprised that a static method is not TYPE_CODE_FUNC.
> > It seems like it should be, because these are really just functions.
>
> I never really questioned it being TYPE_CODE_METHOD, I was just wondering
> instead if there is a flag that tells us that it is a static method.
>
>
> > Hannes> (gdb) py print(b_obj['arg0_func']())
> > Hannes> Traceback (most recent call last):
> > Hannes> File "<string>", line 1, in <module>
> > Hannes> gdb.error: Too few arguments in function call.
> > Hannes> Error while executing Python code.
> > Hannes> (gdb) py print(b_obj['arg0_func'](b_obj))
> > Hannes> 198
> >
> > How does this interact with overloading?
>
> Probably as you expected, it doesn't work, since the [] operator
> of gdb.Value doesn't know what to do:
>
> (gdb) py print(b_obj['overloaded_func'])
> Traceback (most recent call last):
> File "<string>", line 1, in <module>
> gdb.error: cannot resolve overloaded method `overloaded_func': no arguments supplied
> Error while executing Python code.
>
>
> > It seems to me that either b_obj['name'] has to return some kind of
> > overload set, or we need a different API, like b_obj.call_method('name', ...).
> >
> > In the latter case we could have it automatically supply 'this', at
> > least when it's needed.
>
> The overload set would probably be relatively easy to implement, while
> the call_method would be easier to use, if it automatically chooses the
> right one based on the arguments.
>
>
> Regards
>
> Hannes
Ping.
Am Mittwoch, 3. Januar 2024, 11:38:57 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
> Ping.
>
>
> Am Samstag, 16. Dezember 2023, 12:40:25 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
>
> > Am Samstag, 16. Dezember 2023, 01:30:31 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> >
> > > >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
> > >
> > > Hannes> static int static_func ();
> > >
> > > Hannes> (gdb) py b_obj = gdb.parse_and_eval('b_obj')
> > > Hannes> (gdb) py print(b_obj['static_func']())
> > > Hannes> Traceback (most recent call last):
> > > Hannes> File "<string>", line 1, in <module>
> > > Hannes> RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
> > >
> > > I'm a bit surprised that a static method is not TYPE_CODE_FUNC.
> > > It seems like it should be, because these are really just functions.
> >
> > I never really questioned it being TYPE_CODE_METHOD, I was just wondering
> > instead if there is a flag that tells us that it is a static method.
> >
> >
> > > Hannes> (gdb) py print(b_obj['arg0_func']())
> > > Hannes> Traceback (most recent call last):
> > > Hannes> File "<string>", line 1, in <module>
> > > Hannes> gdb.error: Too few arguments in function call.
> > > Hannes> Error while executing Python code.
> > > Hannes> (gdb) py print(b_obj['arg0_func'](b_obj))
> > > Hannes> 198
> > >
> > > How does this interact with overloading?
> >
> > Probably as you expected, it doesn't work, since the [] operator
> > of gdb.Value doesn't know what to do:
> >
> > (gdb) py print(b_obj['overloaded_func'])
> > Traceback (most recent call last):
> > File "<string>", line 1, in <module>
> > gdb.error: cannot resolve overloaded method `overloaded_func': no arguments supplied
> > Error while executing Python code.
> >
> >
> > > It seems to me that either b_obj['name'] has to return some kind of
> > > overload set, or we need a different API, like b_obj.call_method('name', ...).
> > >
> > > In the latter case we could have it automatically supply 'this', at
> > > least when it's needed.
> >
> > The overload set would probably be relatively easy to implement, while
> > the call_method would be easier to use, if it automatically chooses the
> > right one based on the arguments.
> >
> >
> > Regards
> >
> > Hannes
Ping.
Am Mittwoch, 17. Januar 2024, 16:52:56 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
> Ping.
>
>
> Am Mittwoch, 3. Januar 2024, 11:38:57 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
>
> > Ping.
> >
> >
> > Am Samstag, 16. Dezember 2023, 12:40:25 MEZ hat Hannes Domani <ssbssa@yahoo.de> Folgendes geschrieben:
> >
> > > Am Samstag, 16. Dezember 2023, 01:30:31 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> > >
> > > > >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
> > > >
> > > > Hannes> static int static_func ();
> > > >
> > > > Hannes> (gdb) py b_obj = gdb.parse_and_eval('b_obj')
> > > > Hannes> (gdb) py print(b_obj['static_func']())
> > > > Hannes> Traceback (most recent call last):
> > > > Hannes> File "<string>", line 1, in <module>
> > > > Hannes> RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
> > > >
> > > > I'm a bit surprised that a static method is not TYPE_CODE_FUNC.
> > > > It seems like it should be, because these are really just functions.
> > >
> > > I never really questioned it being TYPE_CODE_METHOD, I was just wondering
> > > instead if there is a flag that tells us that it is a static method.
> > >
> > >
> > > > Hannes> (gdb) py print(b_obj['arg0_func']())
> > > > Hannes> Traceback (most recent call last):
> > > > Hannes> File "<string>", line 1, in <module>
> > > > Hannes> gdb.error: Too few arguments in function call.
> > > > Hannes> Error while executing Python code.
> > > > Hannes> (gdb) py print(b_obj['arg0_func'](b_obj))
> > > > Hannes> 198
> > > >
> > > > How does this interact with overloading?
> > >
> > > Probably as you expected, it doesn't work, since the [] operator
> > > of gdb.Value doesn't know what to do:
> > >
> > > (gdb) py print(b_obj['overloaded_func'])
> > > Traceback (most recent call last):
> > > File "<string>", line 1, in <module>
> > > gdb.error: cannot resolve overloaded method `overloaded_func': no arguments supplied
> > > Error while executing Python code.
> > >
> > >
> > > > It seems to me that either b_obj['name'] has to return some kind of
> > > > overload set, or we need a different API, like b_obj.call_method('name', ...).
> > > >
> > > > In the latter case we could have it automatically supply 'this', at
> > > > least when it's needed.
> > >
> > > The overload set would probably be relatively easy to implement, while
> > > the call_method would be easier to use, if it automatically chooses the
> > > right one based on the arguments.
> > >
> > >
> > > Regards
> > >
> > > Hannes
>>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
Hannes> Currently it's not possible to call C++ methods from python.
Hannes> Note that it's necessary to explicitely add the this pointer
Hannes> as the first argument in a call of non-static methods:
While I think it would be good to handle overloading, it occurs to me
that we don't really try to do this for global calls either. And, the
approach you've taken here does not prevent future improvements.
So, I think this is ok. Thank you.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
Am Donnerstag, 8. Februar 2024 um 17:29:11 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
>
> Hannes> Currently it's not possible to call C++ methods from python.
>
> Hannes> Note that it's necessary to explicitely add the this pointer
> Hannes> as the first argument in a call of non-static methods:
>
> While I think it would be good to handle overloading, it occurs to me
> that we don't really try to do this for global calls either. And, the
> approach you've taken here does not prevent future improvements.
>
> So, I think this is ok. Thank you.
>
> Approved-By: Tom Tromey <tom@tromey.com>
Pushed, thanks.
Hannes
@@ -1214,10 +1214,11 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
GDB_PY_HANDLE_EXCEPTION (except);
}
- if (ftype->code () != TYPE_CODE_FUNC)
+ if (ftype->code () != TYPE_CODE_FUNC && ftype->code () != TYPE_CODE_METHOD)
{
PyErr_SetString (PyExc_RuntimeError,
- _("Value is not callable (not TYPE_CODE_FUNC)."));
+ _("Value is not callable (not TYPE_CODE_FUNC"
+ " or TYPE_CODE_METHOD)."));
return NULL;
}
@@ -37,8 +37,33 @@ union U {
class B : public A {
public:
char a;
+
+ static int static_func ();
+ int arg0_func ();
+ int arg1_func (int arg1);
+ int arg2_func (int arg1, int arg2);
};
+int B::static_func ()
+{
+ return 1111;
+}
+
+int B::arg0_func ()
+{
+ return A::a + a;
+}
+
+int B::arg1_func (int arg1)
+{
+ return a * arg1;
+}
+
+int B::arg2_func (int arg1, int arg2)
+{
+ return a * arg1 + arg2;
+}
+
struct X
{
union { int x; char y; };
@@ -99,3 +99,15 @@ gdb_test "python print(uu\[uu_fields\[1\]\]\['a'\])" "1000" "uu.a via field"
# Test overloaded operators.
gdb_test_no_output "python a = gdb.parse_and_eval('a')" "init a"
gdb_test "python print(a + 5)" "10" "a + 5"
+
+# Test inferior function calls of methods.
+gdb_test "py print(b_obj\['static_func'\]())" "1111"
+gdb_test "py print(b_obj\['arg0_func'\]())" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg0_func'\](b_obj))" "198"
+gdb_test "py print(b_obj\['arg1_func'\]())" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg1_func'\](b_obj))" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg1_func'\](b_obj, 3))" "294"
+gdb_test "py print(b_obj\['arg2_func'\]())" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg2_func'\](b_obj))" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg2_func'\](b_obj, 4))" ".*Too few arguments in function call.*"
+gdb_test "py print(b_obj\['arg2_func'\](b_obj, 5, 6))" "496"