swig/Source/Modules/csharp.cxx
William S Fulton 2e0346a3a6 %javamethodmodifiers (java) and %csmethodmodifiers (C#) operate slightly differently.
Previously this had to be present to set the method modifiers. Now this feature is only
used if it exists for the method being wrapped. The default is "public" as previous
however, when wrapping protected director methods it is "protected".


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@5553 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2003-12-13 00:13:10 +00:00

2034 lines
71 KiB
C++

/* -----------------------------------------------------------------------------
* csharp.cxx
*
* CSharp wrapper module.
*
* Author(s) : William Fulton
* Neil Cawse
*
* Copyright (C) 1999-2002. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
char cvsroot_csharp_cxx[] = "$Header$";
#include <limits.h> // for INT_MAX
#include "swigmod.h"
#ifndef MACSWIG
#include "swigconfig.h"
#endif
#include <ctype.h>
class CSHARP : public Language {
static const char *usage;
const String *empty_string;
const String *public_string;
const String *protected_string;
Hash *swig_types_hash;
File *f_runtime;
File *f_header;
File *f_wrappers;
File *f_init;
bool proxy_flag; // Flag for generating proxy classes
bool have_default_constructor_flag;
bool native_function_flag; // Flag for when wrapping a native function
bool enum_constant_flag; // Flag for when wrapping an enum or constant
bool static_flag; // Flag for when wrapping a static functions or member variables
bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
bool global_variable_flag; // Flag for when wrapping a global variable
String *imclass_name; // intermediary class name
String *module_class_name; // module class name
String *imclass_class_code; // intermediary class code
String *proxy_class_def;
String *proxy_class_code;
String *module_class_code;
String *proxy_class_name;
String *variable_name; //Name of a variable being wrapped
String *proxy_class_constants_code;
String *module_class_constants_code;
String *package; // Package name
String *imclass_imports; //intermediary class imports from %pragma
String *module_imports; //module imports from %pragma
String *imclass_baseclass; //inheritance for intermediary class class from %pragma
String *module_baseclass; //inheritance for module class from %pragma
String *imclass_interfaces; //interfaces for intermediary class class from %pragma
String *module_interfaces; //interfaces for module class from %pragma
String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
String *module_class_modifiers; //class modifiers for module class overriden by %pragma
String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
String *destructor_call; //C++ destructor call if any
enum type_additions {none, pointer, reference};
public:
/* -----------------------------------------------------------------------------
* CSHARP()
* ----------------------------------------------------------------------------- */
CSHARP() :
empty_string(NewString("")),
public_string(NewString("public")),
protected_string(NewString("protected")),
swig_types_hash(NULL),
f_runtime(NULL),
f_header(NULL),
f_wrappers(NULL),
f_init(NULL),
proxy_flag(true),
have_default_constructor_flag(false),
native_function_flag(false),
enum_constant_flag(false),
static_flag(false),
variable_wrapper_flag(false),
wrapping_member_flag(false),
global_variable_flag(false),
imclass_name(NULL),
module_class_name(NULL),
imclass_class_code(NULL),
proxy_class_def(NULL),
proxy_class_code(NULL),
module_class_code(NULL),
proxy_class_name(NULL),
variable_name(NULL),
proxy_class_constants_code(NULL),
module_class_constants_code(NULL),
package(NULL),
imclass_imports(NULL),
module_imports(NULL),
imclass_baseclass(NULL),
module_baseclass(NULL),
imclass_interfaces(NULL),
module_interfaces(NULL),
imclass_class_modifiers(NULL),
module_class_modifiers(NULL),
upcasts_code(NULL),
imclass_cppcasts_code(NULL),
destructor_call(NULL)
{
}
/* -----------------------------------------------------------------------------
* getProxyName()
*
* Test to see if a type corresponds to something wrapped with a proxy class
* Return NULL if not otherwise the proxy class name
* ----------------------------------------------------------------------------- */
String *getProxyName(SwigType *t) {
if (proxy_flag) {
Node *n = classLookup(t);
if (n) {
return Getattr(n,"sym:name");
}
}
return NULL;
}
/* ------------------------------------------------------------
* main()
* ------------------------------------------------------------ */
virtual void main(int argc, char *argv[]) {
SWIG_library_directory("csharp");
// Look for certain command line options
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if (strcmp(argv[i],"-package") == 0) {
if (argv[i+1]) {
package = NewString("");
Printf(package, argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i++;
} else {
Swig_arg_error();
}
} else if ((strcmp(argv[i],"-noproxy") == 0)) {
Swig_mark_arg(i);
proxy_flag = false;
} else if (strcmp(argv[i],"-help") == 0) {
Printf(stderr,"%s\n", usage);
}
}
}
// Add a symbol to the parser for conditional compilation
Preprocessor_define("SWIGCSHARP 1",0);
// Add typemap definitions
SWIG_typemap_lang("csharp");
SWIG_config_file("csharp.swg");
allow_overloading();
}
/* ---------------------------------------------------------------------
* top()
* --------------------------------------------------------------------- */
virtual int top(Node *n) {
/* Initialize all of the output files */
String *outfile = Getattr(n,"outfile");
f_runtime = NewFile(outfile,"w");
if (!f_runtime) {
Printf(stderr,"Unable to open %s\n", outfile);
SWIG_exit(EXIT_FAILURE);
}
f_init = NewString("");
f_header = NewString("");
f_wrappers = NewString("");
/* Register file targets with the SWIG file handler */
Swig_register_filebyname("header",f_header);
Swig_register_filebyname("wrapper",f_wrappers);
Swig_register_filebyname("runtime",f_runtime);
Swig_register_filebyname("init",f_init);
swig_types_hash = NewHash();
// Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
Node* optionsnode = Getattr( Getattr(n,"module") ,"options");
if (optionsnode)
if (Getattr(optionsnode,"imclassname"))
imclass_name = Copy(Getattr(optionsnode,"imclassname"));
if (!imclass_name) {
imclass_name = NewStringf("%sPINVOKE", Getattr(n,"name"));
module_class_name = Copy(Getattr(n,"name"));
} else {
// Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
if (Cmp(imclass_name, Getattr(n,"name")) == 0)
module_class_name = NewStringf("%sModule", Getattr(n,"name"));
else
module_class_name = Copy(Getattr(n,"name"));
}
imclass_class_code = NewString("");
proxy_class_def = NewString("");
proxy_class_code = NewString("");
module_class_constants_code = NewString("");
imclass_baseclass = NewString("");
imclass_interfaces = NewString("");
imclass_class_modifiers = NewString(""); // package access only to the intermediary class by default
module_class_code = NewString("");
module_baseclass = NewString("");
module_interfaces = NewString("");
module_imports = NewString("");
module_class_modifiers = NewString("public");
imclass_imports = NewString("");
imclass_cppcasts_code = NewString("");
upcasts_code = NewString("");
if (!package) package = NewString("");
Swig_banner(f_runtime); // Print the SWIG banner message
if (NoInclude) {
Printf(f_runtime,"#define SWIG_NOINCLUDE\n");
}
String *wrapper_name = NewString("");
Printf(wrapper_name, "CSharp_%%f", imclass_name);
Swig_name_register((char*)"wrapper", Char(wrapper_name));
Swig_name_register((char*)"set", (char*)"set_%v");
Swig_name_register((char*)"get", (char*)"get_%v");
Swig_name_register((char*)"member", (char*)"%c_%m");
Delete(wrapper_name);
Printf(f_wrappers,"\n#ifdef __cplusplus\n");
Printf(f_wrappers,"extern \"C\" {\n");
Printf(f_wrappers,"#endif\n\n");
/* Emit code */
Language::top(n);
// Generate the intermediary class
{
String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
File *f_im = NewFile(filen,"w");
if(!f_im) {
Printf(stderr,"Unable to open %s\n", filen);
SWIG_exit(EXIT_FAILURE);
}
Delete(filen); filen = NULL;
// Start writing out the intermediary class
if(Len(package) > 0)
Printf(f_im, "//package %s;\n\n", package);
emitBanner(f_im);
if(imclass_imports)
Printf(f_im, "%s\n", imclass_imports);
if (Len(imclass_class_modifiers) > 0)
Printf(f_im, "%s ", imclass_class_modifiers);
Printf(f_im, "class %s ", imclass_name);
if (imclass_baseclass && *Char(imclass_baseclass))
Printf(f_im, ": %s ", imclass_baseclass);
if (Len(imclass_interfaces) > 0)
Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
Printf(f_im, "{\n");
// Add the intermediary class methods
Replaceall(imclass_class_code,"$module", module_class_name);
Printv(f_im, imclass_class_code, NIL);
Printv(f_im, imclass_cppcasts_code, NIL);
// Finish off the class
Printf(f_im, "}\n");
Close(f_im);
}
// Generate the C# module class
{
String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
File *f_module = NewFile(filen,"w");
if(!f_module) {
Printf(stderr,"Unable to open %s\n", filen);
SWIG_exit(EXIT_FAILURE);
}
Delete(filen); filen = NULL;
// Start writing out the module class
if(Len(package) > 0)
Printf(f_module, "//package %s;\n\n", package);
emitBanner(f_module);
if(module_imports)
Printf(f_module, "%s\n", module_imports);
if (Len(module_class_modifiers) > 0)
Printf(f_module, "%s ", module_class_modifiers);
Printf(f_module, "class %s ", module_class_name);
if (module_baseclass && *Char(module_baseclass))
Printf(f_module, ": %s ", module_baseclass);
if (Len(module_interfaces) > 0)
Printv(f_module, "implements ", module_interfaces, " ", NIL);
Printf(f_module, "{\n");
// Add the wrapper methods
Printv(f_module, module_class_code, NIL);
// Write out all the enums constants
if (Len(module_class_constants_code) != 0 )
Printv(f_module, " // enums and constants\n", module_class_constants_code, NIL);
// Finish off the class
Printf(f_module, "}\n");
Close(f_module);
}
if(upcasts_code)
Printv(f_wrappers,upcasts_code,NIL);
Printf(f_wrappers,"#ifdef __cplusplus\n");
Printf(f_wrappers,"}\n");
Printf(f_wrappers,"#endif\n");
// Output a C# type wrapper class for each SWIG type
for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
emitTypeWrapperClass(swig_type.key, swig_type.item);
}
Delete(swig_types_hash); swig_types_hash = NULL;
Delete(imclass_name); imclass_name = NULL;
Delete(imclass_class_code); imclass_class_code = NULL;
Delete(proxy_class_def); proxy_class_def = NULL;
Delete(proxy_class_code); proxy_class_code = NULL;
Delete(module_class_constants_code); module_class_constants_code = NULL;
Delete(imclass_baseclass); imclass_baseclass = NULL;
Delete(imclass_interfaces); imclass_interfaces = NULL;
Delete(imclass_class_modifiers); imclass_class_modifiers = NULL;
Delete(module_class_name); module_class_name = NULL;
Delete(module_class_code); module_class_code = NULL;
Delete(module_baseclass); module_baseclass = NULL;
Delete(module_interfaces); module_interfaces = NULL;
Delete(module_imports); module_imports = NULL;
Delete(module_class_modifiers); module_class_modifiers = NULL;
Delete(imclass_imports); imclass_imports = NULL;
Delete(imclass_cppcasts_code); imclass_cppcasts_code = NULL;
Delete(upcasts_code); upcasts_code = NULL;
Delete(package); package = NULL;
/* Close all of the files */
Dump(f_header,f_runtime);
Dump(f_wrappers,f_runtime);
Wrapper_pretty_print(f_init,f_runtime);
Delete(f_header);
Delete(f_wrappers);
Delete(f_init);
Close(f_runtime);
Delete(f_runtime);
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* emitBanner()
* ----------------------------------------------------------------------------- */
void emitBanner(File *f) {
Printf(f, "/* ----------------------------------------------------------------------------\n");
Printf(f, " * This file was automatically generated by SWIG (http://www.swig.org).\n");
Printf(f, " * Version: %s\n", PACKAGE_VERSION);
Printf(f, " *\n");
Printf(f, " * Do not make changes to this file unless you know what you are doing--modify\n");
Printf(f, " * the SWIG interface file instead.\n");
Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
}
/* ----------------------------------------------------------------------
* nativeWrapper()
* ---------------------------------------------------------------------- */
virtual int nativeWrapper(Node *n) {
String *wrapname = Getattr(n,"wrap:name");
if (!addSymbol(wrapname,n)) return SWIG_ERROR;
if (Getattr(n,"type")) {
Swig_save("nativeWrapper",n,"name",NIL);
Setattr(n,"name", wrapname);
native_function_flag = true;
functionWrapper(n);
Swig_restore(n);
native_function_flag = false;
} else {
Printf(stderr,"%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n,"wrap:name"));
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* functionWrapper()
* ---------------------------------------------------------------------- */
virtual int functionWrapper(Node *n) {
String *symname = Getattr(n,"sym:name");
SwigType *t = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
String *tm;
Parm *p;
int i;
String *c_return_type = NewString("");
String *im_return_type = NewString("");
String *cleanup = NewString("");
String *outarg = NewString("");
String *body = NewString("");
int num_arguments = 0;
int num_required = 0;
bool is_void_return;
String *overloaded_name = getOverloadedName(n);
if (!Getattr(n,"sym:overloaded")) {
if (!addSymbol(Getattr(n,"sym:name"),n)) return SWIG_ERROR;
}
/*
* Generate the proxy class properties for public member variables.
* Not for enums and constants.
*/
if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
// Capitalize the first letter in the variable in the getter/setter function name
bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
String *getter_setter_name = NewString("");
if(!getter_flag)
Printf(getter_setter_name,"set");
else
Printf(getter_setter_name,"get");
Putc(toupper((int) *Char(variable_name)), getter_setter_name);
Printf(getter_setter_name, "%s", Char(variable_name)+1);
Setattr(n,"proxyfuncname", getter_setter_name);
Setattr(n,"imfuncname", symname);
proxyClassFunctionHandler(n);
Delete(getter_setter_name);
}
/*
The rest of this function deals with generating the intermediary class wrapper function (that wraps
a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
matching PInvoke c function call.
*/
// A new wrapper function object
Wrapper *f = NewWrapper();
// Make a wrapper name for this function
String *wname = Swig_name_wrapper(overloaded_name);
/* Attach the non-standard typemaps to the parameter list. */
Swig_typemap_attach_parms("ctype", l, f);
Swig_typemap_attach_parms("imtype", l, f);
/* Get return types */
if ((tm = Swig_typemap_lookup_new("ctype",n,"",0))) {
Printf(c_return_type,"%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
"No ctype typemap defined for %s\n", SwigType_str(t,0));
}
if ((tm = Swig_typemap_lookup_new("imtype",n,"",0))) {
Printf(im_return_type,"%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number,
"No imtype typemap defined for %s\n", SwigType_str(t,0));
}
is_void_return = (Cmp(c_return_type, "void") == 0);
if (!is_void_return)
Wrapper_add_localv(f,"jresult", c_return_type, "jresult = 0",NIL);
Printv(imclass_class_code,
"\n [DllImport(\"",module_class_name,"\", EntryPoint=\"CSharp_",overloaded_name,"\")]\n", NIL);
Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
Printv(f->def, " DllExport ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
// Emit all of the local variables for holding arguments.
emit_args(t,l,f);
/* Attach the standard typemaps */
emit_attach_parmmaps(l,f);
Setattr(n,"wrap:parms",l);
/* Get number of required and total arguments */
num_arguments = emit_num_arguments(l);
num_required = emit_num_required(l);
int gencomma = 0;
// Now walk the function parameter list and generate code to get arguments
for (i = 0, p=l; i < num_arguments; i++) {
while (checkAttribute(p,"tmap:in:numinputs","0")) {
p = Getattr(p,"tmap:in:next");
}
SwigType *pt = Getattr(p,"type");
String *ln = Getattr(p,"lname");
String *im_param_type = NewString("");
String *c_param_type = NewString("");
String *arg = NewString("");
Printf(arg,"j%s", ln);
/* Get the ctype types of the parameter */
if ((tm = Getattr(p,"tmap:ctype"))) {
Printv(c_param_type, tm, NIL);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
"No ctype typemap defined for %s\n", SwigType_str(pt,0));
}
/* Get the intermediary class parameter types of the parameter */
if ((tm = Getattr(p,"tmap:imtype"))) {
Printv(im_param_type, tm, NIL);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number,
"No imtype typemap defined for %s\n", SwigType_str(pt,0));
}
/* Add parameter to intermediary class method */
if(gencomma) Printf(imclass_class_code, ", ");
Printf(imclass_class_code, "%s %s", im_param_type, arg);
// Add parameter to C function
Printv(f->def, gencomma?", ":"", c_param_type, " ", arg, NIL);
gencomma = 1;
// Get typemap for this argument
if ((tm = Getattr(p,"tmap:in"))) {
addThrows(n, "tmap:in", p);
Replaceall(tm,"$source",arg); /* deprecated */
Replaceall(tm,"$target",ln); /* deprecated */
Replaceall(tm,"$arg",arg); /* deprecated? */
Replaceall(tm,"$input", arg);
Setattr(p,"emit:input", arg);
Printf(f->code,"%s\n", tm);
p = Getattr(p,"tmap:in:next");
} else {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
"Unable to use type %s as a function argument.\n",SwigType_str(pt,0));
p = nextSibling(p);
}
Delete(im_param_type);
Delete(c_param_type);
Delete(arg);
}
/* Insert constraint checking code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:check"))) {
addThrows(n, "tmap:check", p);
Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */
Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
Replaceall(tm,"$input",Getattr(p,"emit:input"));
Printv(f->code,tm,"\n",NIL);
p = Getattr(p,"tmap:check:next");
} else {
p = nextSibling(p);
}
}
/* Insert cleanup code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:freearg"))) {
addThrows(n, "tmap:freearg", p);
Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */
Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
Replaceall(tm,"$input",Getattr(p,"emit:input"));
Printv(cleanup,tm,"\n",NIL);
p = Getattr(p,"tmap:freearg:next");
} else {
p = nextSibling(p);
}
}
/* Insert argument output code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:argout"))) {
addThrows(n, "tmap:argout", p);
Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */
Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */
Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
Replaceall(tm,"$result","jresult");
Replaceall(tm,"$input",Getattr(p,"emit:input"));
Printv(outarg,tm,"\n",NIL);
p = Getattr(p,"tmap:argout:next");
} else {
p = nextSibling(p);
}
}
// Get any C# exception classes in the throws typemap
ParmList *throw_parm_list = NULL;
if ((throw_parm_list = Getattr(n,"throws"))) {
Swig_typemap_attach_parms("throws", throw_parm_list, f);
for (p = throw_parm_list; p; p=nextSibling(p)) {
if ((tm = Getattr(p,"tmap:throws"))) {
addThrows(n, "tmap:throws", p);
}
}
}
if (Cmp(nodeType(n), "constant") == 0) {
// Wrapping a constant hack
Swig_save("functionWrapper",n,"wrap:action",NIL);
// below based on Swig_VargetToFunction()
SwigType *ty = Swig_wrapped_var_type(Getattr(n,"type"));
Setattr(n,"wrap:action", NewStringf("result = (%s) %s;\n", SwigType_lstr(ty,0), Getattr(n, "value")));
}
// Now write code to make the function call
if(!native_function_flag)
emit_action(n,f);
if (Cmp(nodeType(n), "constant") == 0)
Swig_restore(n);
/* Return value if necessary */
if(!native_function_flag) {
if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
addThrows(n, "tmap:out", n);
Replaceall(tm,"$source", "result"); /* deprecated */
Replaceall(tm,"$target", "jresult"); /* deprecated */
Replaceall(tm,"$result","jresult");
Printf(f->code,"%s", tm);
if (Len(tm))
Printf(f->code,"\n");
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s in function %s.\n", SwigType_str(t,0), Getattr(n,"name"));
}
}
/* Output argument output code */
Printv(f->code,outarg,NIL);
/* Output cleanup code */
Printv(f->code,cleanup,NIL);
/* Look to see if there is any newfree cleanup code */
if (Getattr(n,"feature:new")) {
if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) {
addThrows(n, "tmap:newfree", n);
Replaceall(tm,"$source","result"); /* deprecated */
Printf(f->code,"%s\n",tm);
}
}
/* See if there is any return cleanup code */
if(!native_function_flag) {
if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) {
Replaceall(tm,"$source","result"); /* deprecated */
Printf(f->code,"%s\n",tm);
}
}
/* Finish C function and intermediary class function definitions */
Printf(imclass_class_code, ")");
generateThrowsClause(n, imclass_class_code);
Printf(imclass_class_code, ";\n");
Printf(f->def,") {");
if(!is_void_return)
Printv(f->code, " return jresult;\n", NIL);
Printf(f->code, "}\n");
/* Substitute the cleanup code */
Replaceall(f->code,"$cleanup",cleanup);
/* Contract macro modification */
Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
if(!is_void_return)
Replaceall(f->code,"$null","0");
else
Replaceall(f->code,"$null","");
/* Dump the function out */
if(!native_function_flag)
Wrapper_print(f,f_wrappers);
Setattr(n,"wrap:name", wname);
/* Emit warnings for the few cases that can't be overloaded in C# */
if (Getattr(n,"sym:overloaded")) {
if (!Getattr(n,"sym:nextSibling"))
Swig_overload_rank(n);
}
if(!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
moduleClassFunctionHandler(n);
}
Delete(c_return_type);
Delete(im_return_type);
Delete(cleanup);
Delete(outarg);
Delete(body);
Delete(overloaded_name);
DelWrapper(f);
return SWIG_OK;
}
/* -----------------------------------------------------------------------
* variableWrapper()
* ----------------------------------------------------------------------- */
virtual int variableWrapper(Node *n) {
Language::variableWrapper(n);
return SWIG_OK;
}
/* -----------------------------------------------------------------------
* globalvariableHandler()
* ------------------------------------------------------------------------ */
virtual int globalvariableHandler(Node *n) {
SwigType *t = Getattr(n,"type");
String *tm;
// Get the variable type
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
substituteClassname(t, tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
// Output the property's field declaration and accessor methods
Printf(module_class_code, " public static %s %s {", tm, Getattr(n, "sym:name"));
variable_name = Getattr(n,"sym:name");
global_variable_flag = true;
int ret = Language::globalvariableHandler(n);
global_variable_flag = false;
Printf(module_class_code, "\n }\n\n");
return ret;
}
/* -----------------------------------------------------------------------
* constantWrapper()
* ------------------------------------------------------------------------ */
virtual int constantWrapper(Node *n) {
String *symname = Getattr(n,"sym:name");
SwigType *t = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
String *tm;
String *return_type = NewString("");
String *constants_code = NewString("");
SwigType *original_type = t;
if (!addSymbol(symname,n)) return SWIG_ERROR;
bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
/* Adjust the enum type for the Swig_typemap_lookup. We want the same cstype typemap for all the enum items.
* The type of each enum item depends on what value it is assigned, but is usually a C int. */
if (is_enum_item) {
t = NewStringf("enum %s", Getattr(parentNode(n), "sym:name"));
Setattr(n,"type", t);
}
/* Attach the non-standard typemaps to the parameter list. */
Swig_typemap_attach_parms("cstype", l, NULL);
/* Get C# return types */
bool classname_substituted_flag = false;
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
classname_substituted_flag = substituteClassname(t, tm);
Printf(return_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
// Add the stripped quotes back in
String *new_value = NewString("");
Swig_save("constantWrapper",n,"value",NIL);
if(SwigType_type(t) == T_STRING) {
Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
Setattr(n, "value", new_value);
}
else if(SwigType_type(t) == T_CHAR) {
Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
Setattr(n, "value", new_value);
}
// The %csconst feature determines how the constant value is obtained
String *const_feature = Getattr(n,"feature:cs:const");
bool const_feature_flag = const_feature && Cmp(const_feature, "0") != 0;
// enums are wrapped using a public final static int in C#.
// Other constants are wrapped using a public final static [cstype] in C#.
Printf(constants_code, " public %s %s %s = ", (const_feature_flag ? "const" : "static readonly"), return_type, ((proxy_flag && wrapping_member_flag) ? variable_name : symname));
if ((is_enum_item && Getattr(n,"enumvalue") == 0) || !const_feature_flag) {
// Enums without value and default constant handling will work with any type of C constant and initialises the C# variable from C through a PInvoke call.
if(classname_substituted_flag) // This handles function pointers using the %constant directive
Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
else
Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
// Each constant and enum value is wrapped with a separate PInvoke function call
enum_constant_flag = true;
variableWrapper(n);
enum_constant_flag = false;
} else if (is_enum_item) {
// Alternative enum item handling will use the explicit value of the enum item and hope that it compiles as C# code
Printf(constants_code, "%s;\n", Getattr(n,"enumvalue"));
} else {
// Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
Printf(constants_code, "%s;\n", Getattr(n,"value"));
}
if(proxy_flag && wrapping_member_flag)
Printv(proxy_class_constants_code, constants_code, NIL);
else
Printv(module_class_constants_code, constants_code, NIL);
Swig_restore(n);
if (is_enum_item) {
Delete(Getattr(n,"type"));
Setattr(n,"type", original_type);
}
Delete(new_value);
Delete(return_type);
Delete(constants_code);
return SWIG_OK;
}
virtual int insertDirective(Node *n) {
String *code = Getattr(n,"code");
Replaceall(code, "$module", module_class_name);
return Language::insertDirective(n);
}
/* -----------------------------------------------------------------------------
* pragmaDirective()
*
* Valid Pragmas:
* imclassbase - base (extends) for the intermediary class
* imclassclassmodifiers - class modifiers for the intermediary class
* imclasscode - text (C# code) is copied verbatim to the intermediary class
* imclassimports - import statements for the intermediary class
* imclassinterfaces - interface (implements) for the intermediary class
*
* modulebase - base (extends) for the module class
* moduleclassmodifiers - class modifiers for the module class
* modulecode - text (C# code) is copied verbatim to the module class
* moduleimports - import statements for the module class
* moduleinterfaces - interface (implements) for the module class
*
* ----------------------------------------------------------------------------- */
virtual int pragmaDirective(Node *n) {
if (!ImportMode) {
String *lang = Getattr(n,"lang");
String *code = Getattr(n,"name");
String *value = Getattr(n,"value");
if(Strcmp(lang, "csharp") == 0) {
String *strvalue = NewString(value);
Replaceall(strvalue,"\\\"", "\"");
if(Strcmp(code, "imclassbase") == 0) {
Delete(imclass_baseclass);
imclass_baseclass = Copy(strvalue);
}
else if(Strcmp(code, "imclassclassmodifiers") == 0) {
Delete(imclass_class_modifiers);
imclass_class_modifiers = Copy(strvalue);
}
else if(Strcmp(code, "imclasscode") == 0) {
Printf(imclass_class_code, "%s\n", strvalue);
}
else if(Strcmp(code, "imclassimports") == 0) {
Delete(imclass_imports);
imclass_imports = Copy(strvalue);
}
else if(Strcmp(code, "imclassinterfaces") == 0) {
Delete(imclass_interfaces);
imclass_interfaces = Copy(strvalue);
}
else if(Strcmp(code, "modulebase") == 0) {
Delete(module_baseclass);
module_baseclass = Copy(strvalue);
}
else if(Strcmp(code, "moduleclassmodifiers") == 0) {
Delete(module_class_modifiers);
module_class_modifiers = Copy(strvalue);
}
else if(Strcmp(code, "modulecode") == 0) {
Printf(module_class_code, "%s\n", strvalue);
}
else if(Strcmp(code, "moduleimports") == 0) {
Delete(module_imports);
module_imports = Copy(strvalue);
}
else if(Strcmp(code, "moduleinterfaces") == 0) {
Delete(module_interfaces);
module_interfaces = Copy(strvalue);
} else {
Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
}
Delete(strvalue);
}
}
return Language::pragmaDirective(n);
}
/* -----------------------------------------------------------------------------
* emitProxyClassDefAndCPPCasts()
* ----------------------------------------------------------------------------- */
void emitProxyClassDefAndCPPCasts(Node *n) {
String *c_classname = SwigType_namestr(Getattr(n,"name"));
String *c_baseclass = NULL;
String *baseclass = NULL;
String *c_baseclassname = NULL;
String *typemap_lookup_type = Getattr(n,"classtypeobj");
/* Deal with inheritance */
List *baselist = Getattr(n,"bases");
if (baselist) {
Iterator base = First(baselist);
c_baseclassname = Getattr(base.item,"name");
baseclass = Copy(getProxyName(c_baseclassname));
if (baseclass){
c_baseclass = SwigType_namestr(Getattr(base.item,"name"));
}
base = Next(base);
if (base.item) {
Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", typemap_lookup_type, Getattr(base.item,"name"));
}
}
bool derived = baseclass && getProxyName(c_baseclassname);
if (!baseclass)
baseclass = NewString("");
// Inheritance from pure C# classes
const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE);
if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", typemap_lookup_type, pure_baseclass);
}
// Pure C# interfaces
const String *pure_interfaces = typemapLookup(derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
// Start writing the proxy class
Printv(proxy_class_def,
typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements
"\n",
typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
" class $csclassname", // Class name and bases
(derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ?
" : " :
"",
baseclass,
pure_baseclass,
((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
", " :
"",
pure_interfaces,
" {\n",
" private IntPtr swigCPtr;\n", // Member variables for memory handling
derived ?
"" :
" protected bool swigCMemOwn;\n",
"\n",
" ",
typemapLookup("csptrconstructormodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
" $csclassname(IntPtr cPtr, bool cMemoryOwn) ", // Constructor used for wrapping pointers
derived ?
": base($imclassname.$csclassnameTo$baseclass(cPtr), cMemoryOwn) {\n" :
"{\n swigCMemOwn = cMemoryOwn;\n",
" swigCPtr = cPtr;\n",
" }\n",
NIL);
if(!have_default_constructor_flag) { // All proxy classes need a constructor
Printv(proxy_class_def,
"\n",
" protected $csclassname() : this(IntPtr.Zero, false) {\n",
" }\n",
NIL);
}
// C++ destructor is wrapped by the Dispose method
// Note that the method name is specified in a typemap attribute called methodname
String *destruct = NewString("");
const String *tm = NULL;
Node *attributes = NewHash();
String *destruct_methodname = NULL;
if (derived) {
tm = typemapLookup("csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
} else {
tm = typemapLookup("csdestruct", typemap_lookup_type, WARN_NONE, attributes);
destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
}
if (!destruct_methodname) {
Swig_error(input_file, line_number,
"No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
}
// Emit the Finalize and Dispose methods
if (tm) {
// Finalize method
if (*Char(destructor_call)) {
Printv(proxy_class_def,
typemapLookup("csfinalize", typemap_lookup_type, WARN_NONE),
NIL);
}
// Dispose method
Printv(destruct, tm, NIL);
if (*Char(destructor_call))
Replaceall(destruct, "$imcall", destructor_call);
else
Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
if (*Char(destruct))
Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL);
}
Delete(attributes);
Delete(destruct);
// Emit various other methods
Printv(proxy_class_def,
typemapLookup("csgetcptr", typemap_lookup_type, WARN_CSHARP_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code
"\n",
NIL);
// Substitute various strings into the above template
Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
Replaceall(proxy_class_def, "$baseclass", baseclass);
Replaceall(proxy_class_code, "$baseclass", baseclass);
Replaceall(proxy_class_def, "$imclassname", imclass_name);
Replaceall(proxy_class_code, "$imclassname", imclass_name);
// Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
if(derived){
Printv(imclass_cppcasts_code,"\n [DllImport(\"", module_class_name, "\", EntryPoint=\"CSharp_", proxy_class_name ,"To", baseclass ,"\")]\n", NIL);
Printv(imclass_cppcasts_code," public static extern IntPtr ",
"$csclassnameTo$baseclass(IntPtr objectRef);\n",
NIL);
Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
Replaceall(imclass_cppcasts_code, "$baseclass", baseclass);
Printv(upcasts_code,
"DllExport $cbaseclass * SWIGSTDCALL CSharp_$imclazznameTo$imbaseclass",
"($cclass *objectRef) {\n",
" return ($cbaseclass *)objectRef;\n"
"}\n",
"\n",
NIL);
Replaceall(upcasts_code, "$imbaseclass", baseclass);
Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
Replaceall(upcasts_code, "$cclass", c_classname);
}
Delete(baseclass);
}
/* ----------------------------------------------------------------------
* classHandler()
* ---------------------------------------------------------------------- */
virtual int classHandler(Node *n) {
File *f_proxy = NULL;
if (proxy_flag) {
proxy_class_name = NewString(Getattr(n,"sym:name"));
if (!addSymbol(proxy_class_name,n)) return SWIG_ERROR;
if (Cmp(proxy_class_name, imclass_name) == 0) {
Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
SWIG_exit(EXIT_FAILURE);
}
if (Cmp(proxy_class_name, module_class_name) == 0) {
Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
SWIG_exit(EXIT_FAILURE);
}
String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name);
f_proxy = NewFile(filen,"w");
if(!f_proxy) {
Printf(stderr, "Unable to create proxy class file: %s\n", filen);
SWIG_exit(EXIT_FAILURE);
}
Delete(filen); filen = NULL;
emitBanner(f_proxy);
if(Len(package) > 0)
Printf(f_proxy, "//package %s;\n\n", package);
Clear(proxy_class_def);
Clear(proxy_class_code);
have_default_constructor_flag = false;
destructor_call = NewString("");
proxy_class_constants_code = NewString("");
}
Language::classHandler(n);
if (proxy_flag) {
emitProxyClassDefAndCPPCasts(n);
Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
// Write out all the enums and constants
if (Len(proxy_class_constants_code) != 0 )
Printv(f_proxy, " // enums and constants\n", proxy_class_constants_code, NIL);
Printf(f_proxy, "}\n");
Close(f_proxy);
f_proxy = NULL;
Delete(proxy_class_name); proxy_class_name = NULL;
Delete(destructor_call); destructor_call = NULL;
Delete(proxy_class_constants_code); proxy_class_constants_code = NULL;
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* memberfunctionHandler()
* ---------------------------------------------------------------------- */
virtual int memberfunctionHandler(Node *n) {
Language::memberfunctionHandler(n);
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
Setattr(n,"proxyfuncname", Getattr(n, "sym:name"));
Setattr(n,"imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
Delete(overloaded_name);
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* staticmemberfunctionHandler()
* ---------------------------------------------------------------------- */
virtual int staticmemberfunctionHandler(Node *n) {
static_flag = true;
Language::staticmemberfunctionHandler(n);
if (proxy_flag) {
String *overloaded_name = getOverloadedName(n);
String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
Setattr(n,"proxyfuncname", Getattr(n,"sym:name"));
Setattr(n,"imfuncname", intermediary_function_name);
proxyClassFunctionHandler(n);
Delete(overloaded_name);
}
static_flag = false;
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* proxyClassFunctionHandler()
*
* Function called for creating a C# wrapper function around a c++ function in the
* proxy class. Used for both static and non-static C++ class functions.
* C++ class static functions map to C# static functions.
* Two extra attributes in the Node must be available. These are "proxyfuncname" -
* the name of the C# class proxy function, which in turn will call "imfuncname" -
* the intermediary (PInvoke) function name in the intermediary class.
* ----------------------------------------------------------------------------- */
void proxyClassFunctionHandler(Node *n) {
SwigType *t = Getattr(n,"virtual:type") ? Getattr(n,"virtual:type") : Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
String *intermediary_function_name = Getattr(n,"imfuncname");
String *proxy_function_name = Getattr(n,"proxyfuncname");
String *tm;
Parm *p;
int i;
String *imcall = NewString("");
String *return_type = NewString("");
String *function_code = NewString("");
bool setter_flag = false;
if(!proxy_flag) return;
if (l) {
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
l = nextSibling(l);
}
}
/* Attach the non-standard typemaps to the parameter list */
Swig_typemap_attach_parms("in", l, NULL);
Swig_typemap_attach_parms("cstype", l, NULL);
Swig_typemap_attach_parms("csin", l, NULL);
/* Get return types */
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
substituteClassname(t, tm);
Printf(return_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
// Properties
setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
}
/* Start generating the proxy function */
const String *methodmods = Getattr(n,"feature:cs:methodmodifiers");
methodmods = methodmods ? methodmods : (is_protected(n) ? protected_string : public_string);
Printf(function_code, " %s ", methodmods);
if (static_flag)
Printf(function_code, "static ");
if (Getattr(n,"virtual:derived"))
Printf(function_code, "override ");
else if (checkAttribute(n, "storage", "virtual"))
Printf(function_code, "virtual ");
Printf(function_code, "%s %s(", return_type, proxy_function_name);
Printv(imcall, imclass_name, ".", intermediary_function_name, "(", NIL);
if (!static_flag)
Printv(imcall, "swigCPtr", NIL);
emit_mark_varargs(l);
int gencomma = !static_flag;
/* Output each parameter */
for (i = 0, p=l; p; i++) {
/* Ignored varargs */
if (checkAttribute(p,"varargs:ignore","1")) {
p = nextSibling(p);
continue;
}
/* Ignored parameters */
if (checkAttribute(p,"tmap:in:numinputs","0")) {
p = Getattr(p,"tmap:in:next");
continue;
}
/* Ignore the 'this' argument for variable wrappers */
if (!(variable_wrapper_flag && i==0))
{
SwigType *pt = Getattr(p,"type");
String *param_type = NewString("");
/* Get the C# parameter type */
if ((tm = Getattr(p,"tmap:cstype"))) {
substituteClassname(pt, tm);
Printf(param_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(pt,0));
}
if (gencomma)
Printf(imcall, ", ");
String *arg = variable_wrapper_flag ? NewString("value") : makeParameterName(n, p, i);
// Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
if ((tm = Getattr(p,"tmap:csin"))) {
addThrows(n, "tmap:csin", p);
substituteClassname(pt, tm);
Replaceall(tm, "$csinput", arg);
Printv(imcall, tm, NIL);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number,
"No csin typemap defined for %s\n", SwigType_str(pt,0));
}
/* Add parameter to proxy function */
if (gencomma >= 2)
Printf(function_code, ", ");
gencomma = 2;
Printf(function_code, "%s %s", param_type, arg);
Delete(arg);
Delete(param_type);
}
p = Getattr(p,"tmap:in:next");
}
Printf(imcall, ")");
Printf(function_code, ")");
// Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
if ((tm = Swig_typemap_lookup_new("csout",n,"",0))) {
addThrows(n, "tmap:csout", n);
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csout typemap defined for %s\n", SwigType_str(t,0));
}
generateThrowsClause(n, function_code);
Printf(function_code, " %s\n\n", tm ? tm : empty_string);
if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
// Properties
if(setter_flag) {
// Setter method
if ((tm = Swig_typemap_lookup_new("csvarin",n,"",0))) {
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
Printf(proxy_class_code, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csvarin typemap defined for %s\n", SwigType_str(t,0));
}
} else {
// Getter method
if ((tm = Swig_typemap_lookup_new("csvarout",n,"",0))) {
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
Printf(proxy_class_code, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csvarout typemap defined for %s\n", SwigType_str(t,0));
}
}
} else {
// Normal function call
Printv(proxy_class_code, function_code, NIL);
}
Delete(function_code);
Delete(return_type);
Delete(imcall);
}
/* ----------------------------------------------------------------------
* constructorHandler()
* ---------------------------------------------------------------------- */
virtual int constructorHandler(Node *n) {
ParmList *l = Getattr(n,"parms");
String *tm;
Parm *p;
int i;
Language::constructorHandler(n);
if(proxy_flag) {
String *overloaded_name = getOverloadedName(n);
String *imcall = NewString("");
const String *methodmods = Getattr(n,"feature:cs:methodmodifiers");
methodmods = methodmods ? methodmods : (is_protected(n) ? protected_string : public_string);
methodmods = methodmods ? methodmods : public_string;
Printf(proxy_class_code, " %s %s(", methodmods, proxy_class_name);
Printv(imcall, " : this(", imclass_name, ".", Swig_name_construct(overloaded_name), "(", NIL);
/* Attach the non-standard typemaps to the parameter list */
Swig_typemap_attach_parms("in", l, NULL);
Swig_typemap_attach_parms("cstype", l, NULL);
Swig_typemap_attach_parms("csin", l, NULL);
emit_mark_varargs(l);
int gencomma = 0;
/* Output each parameter */
for (i = 0, p=l; p; i++) {
/* Ignored varargs */
if (checkAttribute(p,"varargs:ignore","1")) {
p = nextSibling(p);
continue;
}
/* Ignored parameters */
if (checkAttribute(p,"tmap:in:numinputs","0")) {
p = Getattr(p,"tmap:in:next");
continue;
}
SwigType *pt = Getattr(p,"type");
String *param_type = NewString("");
/* Get the C# parameter type */
if ((tm = Getattr(p,"tmap:cstype"))) {
substituteClassname(pt, tm);
Printf(param_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(pt,0));
}
if (gencomma)
Printf(imcall, ", ");
String *arg = makeParameterName(n, p, i);
// Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
if ((tm = Getattr(p,"tmap:csin"))) {
addThrows(n, "tmap:csin", p);
substituteClassname(pt, tm);
Replaceall(tm, "$csinput", arg);
Printv(imcall, tm, NIL);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number,
"No csin typemap defined for %s\n", SwigType_str(pt,0));
}
/* Add parameter to proxy function */
if(gencomma)
Printf(proxy_class_code, ", ");
Printf(proxy_class_code, "%s %s", param_type, arg);
gencomma = 1;
Delete(arg);
Delete(param_type);
p = Getattr(p,"tmap:in:next");
}
Printf(imcall, "), true)");
Printf(proxy_class_code, ")");
Printf(proxy_class_code,"%s", imcall);
generateThrowsClause(n, proxy_class_code);
Printf(proxy_class_code, " {\n");
Printf(proxy_class_code, " }\n\n");
if(!gencomma) // We must have a default constructor
have_default_constructor_flag = true;
Delete(overloaded_name);
Delete(imcall);
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* destructorHandler()
* ---------------------------------------------------------------------- */
virtual int destructorHandler(Node *n) {
Language::destructorHandler(n);
String *symname = Getattr(n,"sym:name");
if(proxy_flag) {
Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
}
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* membervariableHandler()
* ---------------------------------------------------------------------- */
virtual int membervariableHandler(Node *n) {
SwigType *t = Getattr(n,"type");
String *tm;
// Get the variable type
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
substituteClassname(t, tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
// Output the property's field declaration and accessor methods
Printf(proxy_class_code, " public %s %s {", tm, Getattr(n, "sym:name"));
variable_name = Getattr(n,"sym:name");
wrapping_member_flag = true;
variable_wrapper_flag = true;
Language::membervariableHandler(n);
wrapping_member_flag = false;
variable_wrapper_flag = false;
Printf(proxy_class_code, "\n }\n\n");
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* staticmembervariableHandler()
* ---------------------------------------------------------------------- */
virtual int staticmembervariableHandler(Node *n) {
bool static_const_member_flag = (Getattr(n, "value") == 0);
if(static_const_member_flag) {
SwigType *t = Getattr(n,"type");
String *tm;
// Get the variable type
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
substituteClassname(t, tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
// Output the property's field declaration and accessor methods
Printf(proxy_class_code, " public static %s %s {", tm, Getattr(n, "sym:name"));
}
variable_name = Getattr(n,"sym:name");
wrapping_member_flag = true;
static_flag = true;
Language::staticmembervariableHandler(n);
wrapping_member_flag = false;
static_flag = false;
if(static_const_member_flag)
Printf(proxy_class_code, "\n }\n\n");
return SWIG_OK;
}
/* ----------------------------------------------------------------------
* memberconstantHandler()
* ---------------------------------------------------------------------- */
virtual int memberconstantHandler(Node *n) {
variable_name = Getattr(n,"sym:name");
wrapping_member_flag = true;
Language::memberconstantHandler(n);
wrapping_member_flag = false;
return SWIG_OK;
}
/* -----------------------------------------------------------------------------
* getOverloadedName()
* ----------------------------------------------------------------------------- */
String *getOverloadedName(Node *n) {
/* Although PInvoke functions are designed to handle overloaded functions, a C# IntPtr is used for all classes in the SWIG
* intermediary class. The intermediary class methods are thus mangled when overloaded to give a unique name. */
String *overloaded_name = NewStringf("%s", Getattr(n,"sym:name"));
if (Getattr(n,"sym:overloaded")) {
Printv(overloaded_name, Getattr(n,"sym:overname"), NIL);
}
return overloaded_name;
}
/* -----------------------------------------------------------------------------
* moduleClassFunctionHandler()
* ----------------------------------------------------------------------------- */
void moduleClassFunctionHandler(Node *n) {
SwigType *t = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
String *tm;
Parm *p;
int i;
String *imcall = NewString("");
String *return_type = NewString("");
String *function_code = NewString("");
int num_arguments = 0;
int num_required = 0;
String *overloaded_name = getOverloadedName(n);
String *func_name = NULL;
bool setter_flag = false;
if (l) {
if (SwigType_type(Getattr(l,"type")) == T_VOID) {
l = nextSibling(l);
}
}
/* Attach the non-standard typemaps to the parameter list */
Swig_typemap_attach_parms("cstype", l, NULL);
Swig_typemap_attach_parms("csin", l, NULL);
/* Get return types */
if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
substituteClassname(t, tm);
Printf(return_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(t,0));
}
/* Change function name for global variables */
if (proxy_flag && global_variable_flag) {
// Capitalize the first letter in the variable to create the getter/setter function name
func_name = NewString("");
setter_flag = (Cmp(Getattr(n,"sym:name"), Swig_name_set(variable_name)) == 0);
if(setter_flag)
Printf(func_name,"set");
else
Printf(func_name,"get");
Putc(toupper((int) *Char(variable_name)), func_name);
Printf(func_name, "%s", Char(variable_name)+1);
} else {
func_name = Copy(Getattr(n,"sym:name"));
}
/* Start generating the function */
const String *methodmods = Getattr(n,"feature:cs:methodmodifiers");
methodmods = methodmods ? methodmods : (is_protected(n) ? protected_string : public_string);
Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
/* Get number of required and total arguments */
num_arguments = emit_num_arguments(l);
num_required = emit_num_required(l);
int gencomma = 0;
/* Output each parameter */
for (i = 0, p=l; i < num_arguments; i++) {
/* Ignored parameters */
while (checkAttribute(p,"tmap:in:numinputs","0")) {
p = Getattr(p,"tmap:in:next");
}
SwigType *pt = Getattr(p,"type");
String *param_type = NewString("");
/* Get the C# parameter type */
if ((tm = Getattr(p,"tmap:cstype"))) {
substituteClassname(pt, tm);
Printf(param_type, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
"No cstype typemap defined for %s\n", SwigType_str(pt,0));
}
if (gencomma)
Printf(imcall, ", ");
String *arg = makeParameterName(n, p, i);
// Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
if ((tm = Getattr(p,"tmap:csin"))) {
addThrows(n, "tmap:csin", p);
substituteClassname(pt, tm);
Replaceall(tm, "$csinput", arg);
Printv(imcall, tm, NIL);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number,
"No csin typemap defined for %s\n", SwigType_str(pt,0));
}
/* Add parameter to module class function */
if (gencomma >= 2)
Printf(function_code, ", ");
gencomma = 2;
Printf(function_code, "%s %s", param_type, arg);
p = Getattr(p,"tmap:in:next");
Delete(arg);
Delete(param_type);
}
Printf(imcall, ")");
Printf(function_code, ")");
// Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
if ((tm = Swig_typemap_lookup_new("csout",n,"",0))) {
addThrows(n, "tmap:csout", n);
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csout typemap defined for %s\n", SwigType_str(t,0));
}
generateThrowsClause(n, function_code);
Printf(function_code, " %s\n\n", tm ? tm : empty_string);
if (proxy_flag && global_variable_flag) {
// Properties
if(setter_flag) {
// Setter method
if ((tm = Swig_typemap_lookup_new("csvarin",n,"",0))) {
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
Printf(module_class_code, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csvarin typemap defined for %s\n", SwigType_str(t,0));
}
} else {
// Getter method
if ((tm = Swig_typemap_lookup_new("csvarout",n,"",0))) {
if (Getattr(n,"feature:new"))
Replaceall(tm,"$owner","true");
else
Replaceall(tm,"$owner","false");
substituteClassname(t, tm);
Replaceall(tm, "$imcall", imcall);
Printf(module_class_code, "%s", tm);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
"No csvarout typemap defined for %s\n", SwigType_str(t,0));
}
}
} else {
// Normal function call
Printv(module_class_code, function_code, NIL);
}
Delete(function_code);
Delete(return_type);
Delete(imcall);
Delete(func_name);
}
/* -----------------------------------------------------------------------------
* substituteClassname()
*
* Substitute $csclassname with the proxy class name for classes/structs/unions that SWIG knows about.
* Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
* Inputs:
* pt - parameter type
* tm - cstype typemap
* Outputs:
* tm - cstype typemap with $csclassname substitution
* Return:
* substitution_performed - flag indicating if a substitution was performed
* ----------------------------------------------------------------------------- */
bool substituteClassname(SwigType *pt, String *tm) {
bool substitution_performed = false;
if (Strstr(tm, "$csclassname") || Strstr(tm,"$&csclassname")) {
String *classname = getProxyName(pt);
if (classname) {
Replaceall(tm,"$&csclassname", classname); // getProxyName() works for pointers to classes too
Replaceall(tm,"$csclassname", classname);
}
else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
String *descriptor = NULL;
SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
if (Strstr(tm, "$&csclassname")) {
SwigType_add_pointer(type);
descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
Replaceall(tm, "$&csclassname", descriptor);
}
else { // $csclassname
descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
Replaceall(tm, "$csclassname", descriptor);
}
// Add to hash table so that the type wrapper classes can be created later
Setattr(swig_types_hash, descriptor, type);
Delete(descriptor);
Delete(type);
}
substitution_performed = true;
}
return substitution_performed;
}
/* -----------------------------------------------------------------------------
* makeParameterName()
*
* Inputs:
* n - Node
* p - parameter node
* arg_num - parameter argument number
* Return:
* arg - a unique parameter name
* ----------------------------------------------------------------------------- */
String *makeParameterName(Node *n, Parm *p, int arg_num) {
// Use C parameter name unless it is a duplicate or an empty parameter name
String *pn = Getattr(p,"name");
int count = 0;
ParmList *plist = Getattr(n,"parms");
while (plist) {
if ((Cmp(pn, Getattr(plist,"name")) == 0))
count++;
plist = nextSibling(plist);
}
String *arg = (!pn || (count > 1)) ? NewStringf("arg%d",arg_num) : Copy(Getattr(p,"name"));
return arg;
}
/* -----------------------------------------------------------------------------
* emitTypeWrapperClass()
* ----------------------------------------------------------------------------- */
void emitTypeWrapperClass(String *classname, SwigType *type) {
String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), classname);
File *f_swigtype = NewFile(filen,"w");
String *swigtype = NewString("");
// Emit banner and package name
emitBanner(f_swigtype);
if(Len(package) > 0)
Printf(f_swigtype, "//package %s;\n\n", package);
// Pure C# baseclass and interfaces
const String *pure_baseclass = typemapLookup("csbase", type, WARN_NONE);
const String *pure_interfaces = typemapLookup("csinterfaces", type, WARN_NONE);
// Emit the class
Printv(swigtype,
typemapLookup("csimports", type, WARN_NONE), // Import statements
"\n",
typemapLookup("csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
" class $csclassname", // Class name and bases
*Char(pure_baseclass) ?
" : " :
"",
pure_baseclass,
*Char(pure_interfaces) ? // Interfaces
" : " :
"",
pure_interfaces,
" {\n",
" private IntPtr swigCPtr;\n",
"\n",
" ",
typemapLookup("csptrconstructormodifiers", type, WARN_CSHARP_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
" $csclassname(IntPtr cPtr, bool bFutureUse) {\n", // Constructor used for wrapping pointers
" swigCPtr = cPtr;\n",
" }\n",
"\n",
" protected $csclassname() {\n", // Default constructor
" swigCPtr = IntPtr.Zero;\n",
" }\n",
typemapLookup("csgetcptr", type, WARN_CSHARP_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
typemapLookup("cscode", type, WARN_NONE), // extra C# code
"}\n",
"\n",
NIL);
Replaceall(swigtype, "$csclassname", classname);
Printv(f_swigtype, swigtype, NIL);
Close(f_swigtype);
Delete(filen);
Delete(swigtype);
}
/* -----------------------------------------------------------------------------
* typemapLookup()
* ----------------------------------------------------------------------------- */
const String *typemapLookup(const String *op, String *type, int warning, Node *typemap_attributes=NULL) {
String *tm = NULL;
const String *code = NULL;
if((tm = Swig_typemap_search(op, type, NULL, NULL))) {
code = Getattr(tm,"code");
if (typemap_attributes)
Swig_typemap_attach_kwargs(tm,op,typemap_attributes);
}
if (!code) {
code = empty_string;
if (warning != WARN_NONE)
Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type);
}
return code ? code : empty_string;
}
/* -----------------------------------------------------------------------------
* addThrows()
* ----------------------------------------------------------------------------- */
void addThrows(Node *n, const String *typemap, Node *parameter) {
// Get the comma separated throws clause - held in "throws" attribute in the typemap passed in
String *throws_attribute = NewStringf("%s:throws", typemap);
String *throws = Getattr(parameter,throws_attribute);
if (throws) {
String *throws_list = Getattr(n,"csharp:throwslist");
if (!throws_list) {
throws_list = NewList();
Setattr(n,"csharp:throwslist", throws_list);
}
// Put the exception classes in the throws clause into a temporary List
List *temp_classes_list = Split(throws,',',INT_MAX);
// Add the exception classes to the node throws list, but don't duplicate if already in list
if (temp_classes_list && Len(temp_classes_list) > 0) {
for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
String *exception_class = NewString(cls.item);
Replaceall(exception_class," ",""); // remove spaces
Replaceall(exception_class,"\t",""); // remove tabs
if (Len(exception_class) > 0) {
// $csclassname substitution
SwigType *pt = Getattr(parameter,"type");
substituteClassname(pt, exception_class);
// Don't duplicate the C# exception class in the throws clause
bool found_flag = false;
for (Iterator item = First(throws_list); item.item; item = Next(item)) {
if (Strcmp(item.item, exception_class) == 0)
found_flag = true;
}
if (!found_flag)
Append(throws_list, exception_class);
}
Delete(exception_class);
}
}
Delete(temp_classes_list);
}
Delete(throws_attribute);
}
/* -----------------------------------------------------------------------------
* generateThrowsClause()
* ----------------------------------------------------------------------------- */
void generateThrowsClause(Node *n, String *code) {
// Add the throws clause into code
List *throws_list = Getattr(n,"csharp:throwslist");
if (throws_list) {
Iterator cls = First(throws_list);
Printf(code, " throws %s", cls.item);
while ( (cls = Next(cls)).item)
Printf(code, ", %s", cls.item);
}
}
}; /* class CSHARP */
/* -----------------------------------------------------------------------------
* swig_csharp() - Instantiate module
* ----------------------------------------------------------------------------- */
extern "C" Language *
swig_csharp(void) {
return new CSHARP();
}
/* -----------------------------------------------------------------------------
* Static member variables
* ----------------------------------------------------------------------------- */
const char *CSHARP::usage = (char*)"\
C# Options (available with -csharp)\n\
-package <name> - set name of the assembly to <name>\n\
-noproxy - Generate the low-level functional interface instead\n\
of proxy classes\n\
\n";