%callback and Python class access for C++ static member functions fixes

Fix access to C++ static member functions using Python class
staticmethod syntax, such as Klass.memberfunction instead of
Klass_memberfunction, when using -fastproxy and -builtin in
combination with %callback.

The docstring containing the callback pointers were not being patched
during module initialisation.
This commit is contained in:
William S Fulton 2022-01-14 20:23:43 +00:00
commit 3aa302c08f
4 changed files with 38 additions and 15 deletions

View file

@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2022-01-14: wsfulton
[Python] Fix %callback and specifying the callback function as a
static member function using Python staticmethod syntax, such as
Klass.memberfunction instead of Klass_memberfunction when using
-builtin and -fastproxy.
2022-01-11: wsfulton
[Python] Accept keyword arguments accessing static member functions when
using -builtin and kwargs feature and Python class staticmethod syntax.

View file

@ -1,10 +1,14 @@
import _callback
from callback import *
# callbacks are implemented by modifying docstrings, useful for debugging:
# print("A_bar doc: {}".format(A_bar.__doc__))
# print("A.bar doc: {}".format(A.bar.__doc__))
if foo(2) != 2:
raise RuntimeError
if A_bar(2) != 4:
if A.bar(2) != 4:
raise RuntimeError
if foobar(3, _callback.foo) != foo(3):
@ -13,13 +17,12 @@ if foobar(3, _callback.foo) != foo(3):
if foobar(3, foo) != foo(3):
raise RuntimeError
# Needs some more work for -builtin
# if foobar(3, A.bar) != A.bar(3):
# raise RuntimeError
if foobar(3, A_bar) != A_bar(3):
raise RuntimeError
if foobar(3, A.bar) != A.bar(3):
raise RuntimeError
if foobar(3, foof) != foof(3):
raise RuntimeError

View file

@ -58,15 +58,12 @@ SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
}
}
/* -----------------------------------------------------------------------------*/
/* Fix SwigMethods to carry the callback ptrs when needed */
/* -----------------------------------------------------------------------------*/
/* -----------------------------------------------------------------------------
* Patch %callback methods' docstrings to hold the callback ptrs
* -----------------------------------------------------------------------------*/
SWIGINTERN void
SWIG_Python_FixMethods(PyMethodDef *methods,
swig_const_info *const_table,
swig_type_info **types,
swig_type_info **types_initial) {
SWIG_Python_FixMethods(PyMethodDef *methods, const swig_const_info *const_table, swig_type_info **types, swig_type_info **types_initial) {
size_t i;
for (i = 0; methods[i].ml_name; ++i) {
const char *c = methods[i].ml_doc;
@ -74,7 +71,7 @@ SWIG_Python_FixMethods(PyMethodDef *methods,
c = strstr(c, "swig_ptr: ");
if (c) {
int j;
swig_const_info *ci = 0;
const swig_const_info *ci = 0;
const char *name = c + 10;
for (j = 0; const_table[j].type; ++j) {
if (strncmp(const_table[j].name, name,

View file

@ -73,8 +73,10 @@ static int py3 = 0;
/* C++ Support + Shadow Classes */
static int have_constructor;
static int have_repr;
static int have_constructor = 0;
static int have_repr = 0;
static bool have_builtin_static_member_method_callback = false;
static bool have_fast_proxy_static_member_method_callback = false;
static String *real_classname;
/* Thread Support */
@ -815,6 +817,10 @@ public:
Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n");
Printf(f_wrappers, "%s\n", const_code);
if (have_fast_proxy_static_member_method_callback)
Printf(f_init, " SWIG_Python_FixMethods(SwigMethods_proxydocs, swig_const_table, swig_types, swig_type_initial);\n\n");
initialize_threads(f_init);
Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
@ -2478,6 +2484,7 @@ public:
Printf(methods, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
if (fastproxy) {
Printf(methods_proxydocs, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
have_fast_proxy_static_member_method_callback = true;
}
} else {
Append(methods, "NULL");
@ -3935,6 +3942,10 @@ public:
int funpack = fastunpack;
static String *tp_new = NewString("PyType_GenericNew");
if (have_builtin_static_member_method_callback) {
Printf(f_init, " SWIG_Python_FixMethods(SwigPyBuiltin_%s_methods, swig_const_table, swig_types, swig_type_initial);\n", mname);
}
Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL);
// We cant statically initialize a structure member with a function defined in another C module
@ -4365,6 +4376,7 @@ public:
/* Create new strings for building up a wrapper function */
have_constructor = 0;
have_repr = 0;
have_builtin_static_member_method_callback = false;
class_name = Getattr(n, "sym:name");
real_classname = Getattr(n, "name");
@ -4750,6 +4762,11 @@ public:
String *ds = cdocstring(n, AUTODOC_STATICFUNC);
Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds);
Delete(ds);
} else if (Getattr(n, "feature:callback")) {
String *ds = NewStringf("swig_ptr: %s", Getattr(n, "feature:callback:name"));
Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds);
Delete(ds);
have_builtin_static_member_method_callback = true;
} else {
Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"\" },\n", symname, wname, pyflags);
}