Add cxx{in,out}type typemaps and use them for std::string

This makes using returning strings much simpler to use from C++ code as
the returned pointers don't have to be deleted manually -- although, of
course, this does require an extra allocation and copy and so should be
avoided for the very long strings.

Add a new runtime test showing how simple and convenient it is to use
the functions working with string using the C++ wrappers now.
This commit is contained in:
Vadim Zeitlin 2021-12-06 04:27:23 +01:00
commit fd11a591a3
5 changed files with 135 additions and 30 deletions

View file

@ -611,35 +611,49 @@ public:
}
}
for (; p; p = nextSibling(p)) {
// Static variables use fully qualified names, so we can't just use the name directly.
scoped_dohptr name_ptr;
String* name = Getattr(p, "name");
if (!name) {
// Parameters can also not have any names at all, in which case we use auto-generated one.
name = Getattr(p, "lname");
} else if (Strstr(name, "::")) {
name_ptr = Swig_scopename_last(name);
name = name_ptr.get();
if (p) {
// We want to use readable parameter names in our wrappers instead of the autogenerated arg$N if possible, so do it, and do it before calling
// Swig_typemap_attach_parms(), as this uses the parameter names for typemap expansion.
for (Parm* p2 = p; p2; p2 = nextSibling(p2)) {
String* name = Getattr(p, "name");
if (!name) {
// Can't do anything for unnamed parameters.
continue;
}
// Static variables use fully qualified names, so we need to strip the scope from them.
scoped_dohptr name_ptr;
if (Strstr(name, "::")) {
name_ptr = Swig_scopename_last(name);
name = name_ptr.get();
}
Setattr(p, "lname", name);
}
const type_desc ptype_desc = lookup_cxx_parm_type(n, p);
if (!ptype_desc.type()) {
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, Getfile(p), Getline(p),
"No ctype typemap defined for the parameter \"%s\" of %s\n",
name,
Getattr(n, "sym:name")
);
return;
Swig_typemap_attach_parms("cxxin", p, NULL);
for (; p; p = nextSibling(p)) {
String* const name = Getattr(p, "lname");
const cxx_ptype_desc ptype_desc = lookup_cxx_parm_type(n, p);
if (!ptype_desc.type()) {
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, Getfile(p), Getline(p),
"No ctype typemap defined for the parameter \"%s\" of %s\n",
name,
Getattr(n, "sym:name")
);
return;
}
if (Len(parms_cxx))
Append(parms_cxx, ", ");
Printv(parms_cxx, ptype_desc.type(), " ", name, NIL);
if (Len(parms_call))
Append(parms_call, ", ");
Append(parms_call, ptype_desc.get_param_code(name));
}
if (Len(parms_cxx))
Append(parms_cxx, ", ");
Printv(parms_cxx, ptype_desc.type(), " ", name, NIL);
if (Len(parms_call))
Append(parms_call, ", ");
Append(parms_call, ptype_desc.get_param_code(name));
}
// Avoid checking for exceptions unnecessarily. Note that this is more than an optimization: we'd get into infinite recursion if we checked for exceptions
@ -1006,6 +1020,9 @@ private:
// The logic here is somewhat messy because we use the same "$resolved_type*" typemap for pointers/references to both enums and classes, but we actually
// need to do quite different things for them. It could probably be simplified by changing the typemaps to be distinct, but this would require also updating
// the code for C wrappers generation in substituteResolvedTypeSpecialVariable().
//
// An even better idea might be to try to define this using cxx{in,out} typemaps for the various types and let the generic SWIG machinery do all the
// matching instead of doing it in the code here.
scoped_dohptr resolved_type(SwigType_typedef_resolve_all(type));
scoped_dohptr base_resolved_type(SwigType_base(resolved_type));
@ -1182,11 +1199,23 @@ private:
// Ensure our own replaceSpecialVariables() is used for $typemap() expansion.
temp_ptr_setter<cxx_ptype_desc*> set(&ptype_desc_, &ptype_desc);
if (String* type = Swig_typemap_lookup("ctype", p, "", NULL)) {
bool use_cxxin = true;
String* type = Swig_typemap_lookup("cxxintype", p, "", NULL);
if (!type) {
use_cxxin = false;
type = Swig_typemap_lookup("ctype", p, "", NULL);
}
if (type) {
ptype_desc.set_type(type);
do_resolve_type(n, Getattr(p, "type"), ptype_desc.type(), &ptype_desc, NULL);
}
if (use_cxxin) {
if (String* in_tm = Getattr(p, "tmap:cxxin"))
ptype_desc.apply_in_typemap(Copy(in_tm));
}
return ptype_desc;
}
@ -1194,13 +1223,24 @@ private:
// As above, ensure our replaceSpecialVariables() is used.
temp_ptr_setter<cxx_rtype_desc*> set(&rtype_desc_, &rtype_desc);
String* type = Swig_typemap_lookup("ctype", n, "", NULL);
bool use_cxxout = true;
String* type(Swig_typemap_lookup("cxxouttype", n, "", NULL));
if (!type) {
use_cxxout = false;
type = Swig_typemap_lookup("ctype", n, "", NULL);
}
if (!type)
return false;
rtype_desc.set_type(type);
do_resolve_type(n, Getattr(n, "type"), rtype_desc.type(), NULL, &rtype_desc);
if (use_cxxout) {
if (String* out_tm = Swig_typemap_lookup("cxxout", n, "", NULL))
rtype_desc.apply_out_typemap(out_tm);
}
return true;
}