Change the generated names for the global functions
Prefix them with namespace-based prefix (e.g. "ns1_ns2_" for a function inside ns1::ns2) if feature:nspace is on. Otherwise, or if the function is defined in the global namespace, use the module name as prefix instead of "_wrap": this is slightly less ugly and results in more unique names.
This commit is contained in:
parent
2d13e18d07
commit
f1ab6b7ef2
2 changed files with 45 additions and 12 deletions
|
|
@ -63,7 +63,6 @@ Flattening C++ language constructs into a set of C-style functions obviously com
|
|||
|
||||
<H3>Known C++ Shortcomings in Generated C API:</H3>
|
||||
<ul>
|
||||
<li>Namespaced global functions are not namespaced</li>
|
||||
<li>Enums with a context like class or namespace are broken</li>
|
||||
<li>Global variables are not supported</li>
|
||||
<li>Qualifiers are stripped</li>
|
||||
|
|
@ -192,11 +191,11 @@ Wrapping C functions and variables is obviously performed in a straightforward w
|
|||
|
||||
|
||||
<p>
|
||||
For each C function declared in the interface file a wrapper function with the prefix <tt>_wrap_</tt> is created. Basically, the wrapper function performs a call to the original function, and returns its result. For convenience, a <tt>#define func _wrap_func</tt> is also provided in the generated header file to make it possible to call the function under its original name. If this is undesirable, <tt>SWIG_NO_WRAPPER_ALIASES</tt> can be predefined before including the wrapper header to disable these defines.
|
||||
For each C function declared in the interface file a wrapper function with a prefix, required to make its name different from the original one, is created. The prefix for the global functions is <tt>module_</tt>, i.e. the name of the SWIG module followed by underscore. If <tt>nspace</tt> feature is used, the prefix for a function defined in a namespace is <tt>namespace_</tt> -- note that it does <em>not</em> contain the module prefix, as it's not necessary to make a unique function name in this case. The wrapper function performs a call to the original function, and returns its result. For convenience, a <tt>#define func prefix_func</tt> is also provided in the generated header file to make it possible to call the function under its original name. If this is undesirable, <tt>SWIG_NO_WRAPPER_ALIASES</tt> can be predefined before including the wrapper header to disable these defines.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, for function declaration:
|
||||
For example, for function declaration in the module <tt>mymath</tt>:
|
||||
</p>
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
|
|
@ -208,7 +207,7 @@ The output is simply:
|
|||
</p>
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
int _wrap_gcd(int arg1, int arg2) {
|
||||
int mymath_gcd(int arg1, int arg2) {
|
||||
int result;
|
||||
result = gcd(arg1,arg2);
|
||||
return result;
|
||||
|
|
@ -426,7 +425,7 @@ area: 7.068583
|
|||
Typecasts wrapper functions return values in proxy functions</br>
|
||||
<code>
|
||||
MyClass *MyClass_new(void) {</br>
|
||||
return (MyClass *)_wrap_MyClass_new();</br>
|
||||
return (MyClass *)MyClass_new();</br>
|
||||
}
|
||||
</code>
|
||||
</td>
|
||||
|
|
@ -436,7 +435,7 @@ area: 7.068583
|
|||
<td>Mapping of wrapper functions parameters to local C++ variables</br>
|
||||
</br>
|
||||
<code>
|
||||
SwigObj* _wrap_MyClass_do(SwigObj *carg1) {</br>
|
||||
SwigObj* MyClass_do(SwigObj *carg1) {</br>
|
||||
SomeCPPClass *arg1 = 0;</br>
|
||||
if (carg1)</br>
|
||||
arg1 = (SomeCPPClass*)carg1->obj</br>
|
||||
|
|
@ -500,7 +499,7 @@ void SomeIntTemplateClass_delete(SomeIntTemplateClass * carg1);
|
|||
We'll examine the generation of the wrapper function first.
|
||||
|
||||
<div class="targetlang"><pre>
|
||||
SWIGEXPORTC SwigObj * _wrap_someFunction(SwigObj * carg1, int carg2) {
|
||||
SWIGEXPORTC SwigObj * module_someFunction(SwigObj * carg1, int carg2) {
|
||||
SomeClass * cppresult;
|
||||
SomeTemplateClass< int > *arg1 = 0 ;
|
||||
int arg2 ;
|
||||
|
|
@ -544,7 +543,7 @@ Let's go through it step by step and start with the wrapper prototype
|
|||
<div class="targetlang"><pre>
|
||||
ctype ctype ctype
|
||||
--------- --------- ---
|
||||
SwigObj * _wrap_someFunction(SwigObj * carg1, int carg2);
|
||||
SwigObj * module_someFunction(SwigObj * carg1, int carg2);
|
||||
</pre></div>
|
||||
|
||||
As first unit of the wrapper code, a variable to hold the return value of the function is emitted to the wrapper's body
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ class C:public Language {
|
|||
|
||||
String *empty_string;
|
||||
|
||||
// Prefix for module-level symbols, currently just the module name.
|
||||
String *module_prefix;
|
||||
|
||||
// Used only while generating wrappers for an enum, initially true and reset to false as soon as we see any enum elements.
|
||||
bool enum_is_empty;
|
||||
|
||||
|
|
@ -152,10 +155,15 @@ public:
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
C() :
|
||||
empty_string(NewString(""))
|
||||
empty_string(NewString("")),
|
||||
module_prefix(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~C()
|
||||
{
|
||||
Delete(module_prefix);
|
||||
}
|
||||
|
||||
String *getNamespacedName(Node *n)
|
||||
{
|
||||
|
|
@ -182,6 +190,31 @@ public:
|
|||
return proxyname;
|
||||
}
|
||||
|
||||
// Construct the name to be used for a global (i.e. not member) symbol in C wrappers.
|
||||
//
|
||||
// The returned string must be freed by caller.
|
||||
String *getGlobalWrapperName(Node *n, String *name) const
|
||||
{
|
||||
// Use namespace as the prefix if feature:nspace is in use.
|
||||
scoped_dohptr scopename_prefix(Swig_scopename_prefix(Getattr(n, "name")));
|
||||
if (scopename_prefix) {
|
||||
if (GetFlag(parentNode(n), "feature:nspace")) {
|
||||
scoped_dohptr mangled_prefix(Swig_string_mangle(scopename_prefix));
|
||||
scopename_prefix = mangled_prefix;
|
||||
} else {
|
||||
scopename_prefix.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the module name if we don't use feature:nspace or are outside of any namespace.
|
||||
//
|
||||
// Note that we really, really need to use some prefix, as a global wrapper function can't have the same name as the original function (being wrapped) with
|
||||
// the same name.
|
||||
String* const prefix = scopename_prefix ? scopename_prefix : module_prefix;
|
||||
|
||||
return NewStringf("%s_%s", prefix, name);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* getProxyName()
|
||||
*
|
||||
|
|
@ -386,6 +419,7 @@ public:
|
|||
|
||||
virtual int top(Node *n) {
|
||||
String *module = Getattr(n, "name");
|
||||
module_prefix = Copy(module);
|
||||
String *outfile = Getattr(n, "outfile");
|
||||
|
||||
// initialize I/O
|
||||
|
|
@ -632,7 +666,7 @@ public:
|
|||
{
|
||||
// this is C function, we don't apply typemaps to it
|
||||
String *name = Getattr(n, "sym:name");
|
||||
String *wname = Swig_name_wrapper(name);
|
||||
String *wname = getGlobalWrapperName(n, name);
|
||||
SwigType *type = Getattr(n, "type");
|
||||
SwigType *return_type = NULL;
|
||||
String *arg_names = NULL;
|
||||
|
|
@ -852,7 +886,7 @@ public:
|
|||
|
||||
// C++ function wrapper proxy code
|
||||
bool const is_global = GetFlag(n, "c:globalfun");
|
||||
String *wname = is_global ? Swig_name_wrapper(name) : Copy(name);
|
||||
String *wname = is_global ? getGlobalWrapperName(n, name) : Copy(name);
|
||||
String *preturn_type = get_wrapper_func_return_type(n);
|
||||
String *wrapper_call = NewString("");
|
||||
|
||||
|
|
@ -885,7 +919,7 @@ public:
|
|||
SwigType *type = Getattr(n, "type");
|
||||
SwigType *otype = Copy(type);
|
||||
SwigType *return_type = get_wrapper_func_return_type(n);
|
||||
String *wname = GetFlag(n, "c:globalfun") ? Swig_name_wrapper(name) : Copy(name);
|
||||
String *wname = GetFlag(n, "c:globalfun") ? getGlobalWrapperName(n, name) : Copy(name);
|
||||
ParmList *parms = Getattr(n, "parms");
|
||||
Parm *p;
|
||||
bool is_void_return = (SwigType_type(type) == T_VOID);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue