From: Hannes Domani Date: Thu, 8 Feb 2024 19:09:25 +0000 (+0100) Subject: Allow calling of C++ methods from python X-Git-Tag: gdb-15-branchpoint~1033 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e08907d0672711617f71ef4604df190106b992e;p=thirdparty%2Fbinutils-gdb.git Allow calling of C++ methods from python 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 "", line 1, in 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 "", line 1, in 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 Approved-By: Tom Tromey --- diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 151b8801b88..89ca0982e59 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -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; } diff --git a/gdb/testsuite/gdb.python/py-value-cc.cc b/gdb/testsuite/gdb.python/py-value-cc.cc index c0e68c1174a..2d38a26d948 100644 --- a/gdb/testsuite/gdb.python/py-value-cc.cc +++ b/gdb/testsuite/gdb.python/py-value-cc.cc @@ -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; }; diff --git a/gdb/testsuite/gdb.python/py-value-cc.exp b/gdb/testsuite/gdb.python/py-value-cc.exp index f58acd21ccf..17a67e20c1c 100644 --- a/gdb/testsuite/gdb.python/py-value-cc.exp +++ b/gdb/testsuite/gdb.python/py-value-cc.exp @@ -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"