Factor out C++ function generation into cxx_function_wrapper
No real changes, just factor out the code for (non-special) functions generation from emit_member_function() into a separate cxx_function_wrapper class, so that it could be reused for the global functions generation too.
This commit is contained in:
parent
730384834d
commit
57ba3a7245
1 changed files with 154 additions and 102 deletions
|
|
@ -813,6 +813,135 @@ public:
|
|||
Node* node_func_;
|
||||
};
|
||||
|
||||
/*
|
||||
cxx_function_wrapper
|
||||
|
||||
Outputs the C++ wrapper function. It's different from the C function because it is declared inside the namespace and so doesn't need the usual prefix and may
|
||||
also have different parameter and return types when objects and/or cxx{in,out}type typemaps are involved.
|
||||
*/
|
||||
class cxx_function_wrapper
|
||||
{
|
||||
public:
|
||||
// Call can_wrap() to check if this wrapper can be emitted later.
|
||||
explicit cxx_function_wrapper(cxx_wrappers& cxx_wrappers, Node* n, Parm* p) : cxx_wrappers_(cxx_wrappers) {
|
||||
func_node = NULL;
|
||||
|
||||
except_check_start =
|
||||
except_check_end = "";
|
||||
|
||||
// Usually generating wrappers for overloaded methods is fine, but sometimes their types can clash after applying typemaps and in this case we have no
|
||||
// choice but to avoid generating them, as otherwise we'd just generate uncompilable code.
|
||||
if (Getattr(n, "sym:overloaded")) {
|
||||
Swig_overload_check(n);
|
||||
if (Getattr(n, "overload:ignore"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cxx_wrappers_.lookup_cxx_ret_type(rtype_desc, n))
|
||||
return;
|
||||
|
||||
parms_cxx = NewStringEmpty();
|
||||
parms_call = NewStringEmpty();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Swig_typemap_attach_parms("cxxin", p, NULL);
|
||||
|
||||
for (; p; p = nextSibling(p)) {
|
||||
String* const name = Getattr(p, "lname");
|
||||
|
||||
cxx_ptype_desc ptype_desc;
|
||||
if (!cxx_wrappers_.lookup_cxx_parm_type(ptype_desc, n, p))
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Avoid checking for exceptions unnecessarily. Note that this is more than an optimization: we'd get into infinite recursion if we checked for exceptions
|
||||
// thrown by members of SWIG_CException itself if we didn't do it.
|
||||
if (cxx_wrappers_.is_exception_support_enabled() &&
|
||||
!Checkattr(n, "noexcept", "true") &&
|
||||
(!Checkattr(n, "throw", "1") || Getattr(n, "throws"))) {
|
||||
except_check_start = cxx_wrappers_.except_check_start;
|
||||
except_check_end = cxx_wrappers_.except_check_end;
|
||||
}
|
||||
|
||||
// Everything is fine, so set func_node to indicate success.
|
||||
func_node = n;
|
||||
}
|
||||
|
||||
bool can_wrap() const { return func_node != NULL; }
|
||||
|
||||
// Emit just the function body, including the braces around it.
|
||||
void emit_body(String* wparms) {
|
||||
String* const wname = Getattr(func_node, "wrap:name");
|
||||
|
||||
Append(cxx_wrappers_.sect_impls, "{");
|
||||
|
||||
if (rtype_desc.is_void()) {
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
" ", wname, "(", wparms, "); ",
|
||||
NIL
|
||||
);
|
||||
|
||||
if (*except_check_start != '\0') {
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
except_check_start,
|
||||
except_check_end,
|
||||
"; ",
|
||||
NIL
|
||||
);
|
||||
}
|
||||
} else {
|
||||
rtype_desc.set_return_value(NewStringf("%s%s(%s)%s", except_check_start, wname, wparms, except_check_end));
|
||||
Append(cxx_wrappers_.sect_impls, rtype_desc.get_return_code());
|
||||
}
|
||||
|
||||
Append(cxx_wrappers_.sect_impls, "}\n");
|
||||
}
|
||||
|
||||
|
||||
cxx_wrappers& cxx_wrappers_;
|
||||
Node* func_node;
|
||||
cxx_rtype_desc rtype_desc;
|
||||
scoped_dohptr parms_cxx;
|
||||
scoped_dohptr parms_call;
|
||||
const char* except_check_start;
|
||||
const char* except_check_end;
|
||||
|
||||
private:
|
||||
// Non copyable.
|
||||
cxx_function_wrapper(const cxx_function_wrapper&);
|
||||
cxx_function_wrapper& operator=(const cxx_function_wrapper&);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
cxx_class_wrapper
|
||||
|
||||
|
|
@ -911,32 +1040,12 @@ public:
|
|||
if (Checkattr(n, "storage", "friend"))
|
||||
return;
|
||||
|
||||
// Usually generating wrappers for overloaded methods is fine, but sometimes their types can clash after applying typemaps and in this case we have no
|
||||
// choice but to avoid generating them, as otherwise we'd just generate uncompilable code.
|
||||
if (Getattr(n, "sym:overloaded")) {
|
||||
Swig_overload_check(n);
|
||||
if (Getattr(n, "overload:ignore"))
|
||||
return;
|
||||
}
|
||||
|
||||
temp_ptr_setter<Node*> set(&cxx_wrappers_.node_func_, n);
|
||||
|
||||
// As mentioned elsewhere, we can't use Swig_storage_isstatic() here because the "storage" attribute is temporarily saved in another view when this
|
||||
// function is being executed, so rely on another attribute to determine if it's a static function instead.
|
||||
const bool is_member = Checkattr(n, "ismember", "1");
|
||||
const bool is_static = is_member && Getattr(n, "cplus:staticbase");
|
||||
const bool is_ctor = Checkattr(n, "nodeType", "constructor");
|
||||
|
||||
// Deal with the return type: it may be different from the type of the C wrapper function if it involves objects, and so we may need to add a cast.
|
||||
|
||||
cxx_rtype_desc rtype_desc;
|
||||
if (!cxx_wrappers_.lookup_cxx_ret_type(rtype_desc, n))
|
||||
return;
|
||||
|
||||
// We also need the list of parameters to take in the C++ function being generated and the list of them to pass to the C wrapper.
|
||||
scoped_dohptr parms_cxx(NewStringEmpty());
|
||||
scoped_dohptr parms_call(NewStringEmpty());
|
||||
|
||||
Parm* p = Getattr(n, "parms");
|
||||
if (p && is_member && !is_ctor && !is_static) {
|
||||
// We should have "this" as the first parameter and we need to just skip it, as we handle it specially in C++ wrappers.
|
||||
|
|
@ -951,59 +1060,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
cxx_function_wrapper func_wrapper(cxx_wrappers_, n, p);
|
||||
if (!func_wrapper.can_wrap())
|
||||
return;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
Swig_typemap_attach_parms("cxxin", p, NULL);
|
||||
|
||||
for (; p; p = nextSibling(p)) {
|
||||
String* const name = Getattr(p, "lname");
|
||||
|
||||
cxx_ptype_desc ptype_desc;
|
||||
if (!cxx_wrappers_.lookup_cxx_parm_type(ptype_desc, n, p))
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid checking for exceptions unnecessarily. Note that this is more than an optimization: we'd get into infinite recursion if we checked for exceptions
|
||||
// thrown by members of SWIG_CException itself if we didn't do it.
|
||||
const char* except_check_start = cxx_wrappers_.except_check_start;
|
||||
const char* except_check_end = cxx_wrappers_.except_check_end;
|
||||
if (cxx_wrappers_.is_exception_support_enabled()) {
|
||||
if (Checkattr(n, "noexcept", "true") || (Checkattr(n, "throw", "1") && !Getattr(n, "throws"))) {
|
||||
except_check_start =
|
||||
except_check_end = "";
|
||||
}
|
||||
}
|
||||
// Define aliases for the stuff actually stored in the function wrapper object.
|
||||
cxx_rtype_desc& rtype_desc = func_wrapper.rtype_desc;
|
||||
String* const parms_cxx = func_wrapper.parms_cxx;
|
||||
String* const parms_call = func_wrapper.parms_call;
|
||||
|
||||
// For some reason overloaded functions use fully-qualified name, so we can't just use the name directly.
|
||||
scoped_dohptr name_ptr(Swig_scopename_last(Getattr(n, "name")));
|
||||
String* const name = name_ptr.get();
|
||||
String* const name = name_ptr;
|
||||
String* const wname = Getattr(n, "wrap:name");
|
||||
|
||||
String* const classname = Getattr(class_node_, "sym:name");
|
||||
|
|
@ -1018,8 +1086,8 @@ public:
|
|||
);
|
||||
} else if (Checkattr(n, "memberset", "1")) {
|
||||
Printv(cxx_wrappers_.sect_decls,
|
||||
cindent, "void ", name, "(", parms_cxx.get(), ") "
|
||||
"{ ", Getattr(n, "sym:name"), "(swig_self(), ", parms_call.get(), "); }\n",
|
||||
cindent, "void ", name, "(", parms_cxx, ") "
|
||||
"{ ", Getattr(n, "sym:name"), "(swig_self(), ", parms_call, "); }\n",
|
||||
NIL
|
||||
);
|
||||
} else if (Checkattr(n, "varget", "1")) {
|
||||
|
|
@ -1031,8 +1099,8 @@ public:
|
|||
);
|
||||
} else if (Checkattr(n, "varset", "1")) {
|
||||
Printv(cxx_wrappers_.sect_decls,
|
||||
cindent, "static void ", name, "(", parms_cxx.get(), ") "
|
||||
"{ ", Getattr(n, "sym:name"), "(", parms_call.get(), "); }\n",
|
||||
cindent, "static void ", name, "(", parms_cxx, ") "
|
||||
"{ ", Getattr(n, "sym:name"), "(", parms_call, "); }\n",
|
||||
NIL
|
||||
);
|
||||
} else {
|
||||
|
|
@ -1044,16 +1112,16 @@ public:
|
|||
} else if (is_ctor) {
|
||||
// Delegate to the ctor from opaque C pointer taking ownership of the object.
|
||||
Printv(cxx_wrappers_.sect_decls,
|
||||
cindent, classname, "(", parms_cxx.get(), ");\n",
|
||||
cindent, classname, "(", parms_cxx, ");\n",
|
||||
NIL
|
||||
);
|
||||
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
"inline ", classname, "::", classname, "(", parms_cxx.get(), ") : ",
|
||||
"inline ", classname, "::", classname, "(", parms_cxx, ") : ",
|
||||
classname, "{",
|
||||
except_check_start,
|
||||
wname, "(", parms_call.get(), ")",
|
||||
except_check_end,
|
||||
func_wrapper.except_check_start,
|
||||
wname, "(", parms_call, ")",
|
||||
func_wrapper.except_check_end,
|
||||
"} {}\n",
|
||||
NIL
|
||||
);
|
||||
|
|
@ -1100,39 +1168,20 @@ public:
|
|||
Printv(cxx_wrappers_.sect_decls,
|
||||
cindent,
|
||||
is_static ? "static " : get_virtual_prefix(n), rtype_desc.type(), " ",
|
||||
name, "(", parms_cxx.get(), ")",
|
||||
name, "(", parms_cxx, ")",
|
||||
get_const_suffix(n), ";\n",
|
||||
NIL
|
||||
);
|
||||
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
"inline ", rtype_desc.type(), " ",
|
||||
classname, "::", name, "(", parms_cxx.get(), ")",
|
||||
classname, "::", name, "(", parms_cxx, ")",
|
||||
get_const_suffix(n),
|
||||
" {",
|
||||
" ",
|
||||
NIL
|
||||
);
|
||||
|
||||
if (rtype_desc.is_void()) {
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
" ", wname, "(", wparms.get(), "); ",
|
||||
NIL
|
||||
);
|
||||
|
||||
if (*except_check_start) {
|
||||
Printv(cxx_wrappers_.sect_impls,
|
||||
except_check_start,
|
||||
except_check_end,
|
||||
"; ",
|
||||
NIL
|
||||
);
|
||||
}
|
||||
} else {
|
||||
rtype_desc.set_return_value(NewStringf("%s%s(%s)%s", except_check_start, wname, wparms.get(), except_check_end));
|
||||
Append(cxx_wrappers_.sect_impls, rtype_desc.get_return_code());
|
||||
}
|
||||
|
||||
Append(cxx_wrappers_.sect_impls, "}\n");
|
||||
func_wrapper.emit_body(wparms);
|
||||
} else {
|
||||
// This is something we don't know about
|
||||
Swig_warning(WARN_C_UNSUPPORTTED, Getfile(n), Getline(n),
|
||||
|
|
@ -2401,8 +2450,11 @@ public:
|
|||
emit_wrapper_func_decl(n, wname);
|
||||
|
||||
if (cxx_wrappers_.is_initialized()) {
|
||||
if (cxx_class_wrapper_)
|
||||
temp_ptr_setter<Node*> set(&cxx_wrappers_.node_func_, n);
|
||||
|
||||
if (cxx_class_wrapper_) {
|
||||
cxx_class_wrapper_->emit_member_function(n);
|
||||
}
|
||||
}
|
||||
|
||||
Delete(name);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue