%module special_variable_macros // test $typemap() special variable function // these tests are not typical of how $typemap() should be used, but it checks that it is mostly working %warnfilter(SWIGWARN_GO_NAME_CONFLICT); /* Ignoring 'NewName' due to Go name ('NewName') conflict with 'Name' */ %{ #if defined(_MSC_VER) #pragma warning(disable: 4996) // 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. #endif %} %ignore Name::operator=; %inline %{ struct Name { Name(const char *n="none") : name(strdup(n ? n : "")) {} Name(const Name& x) : name(strdup(x.name)) {} Name& operator= (const Name& x) { if (this != &x) { free(this->name); this->name = strdup(x.name); } return *this; } ~Name () { free(this->name); } const char *getName() const { return name; }; Name *getNamePtr() { return this; }; private: char *name; }; struct NameWrap { NameWrap(const char *n="casternone") : name(n) {} Name *getNamePtr() { return &name; }; private: Name name; }; %} // check $1 and $input get expanded properly when used from $typemap() %typemap(in) Name *GENERIC ($*1_type temp) %{ /*%typemap(in) Name *GENERIC start */ temp = Name("$specialname"); (void)$input; $1 = ($1_ltype) &temp; /*%typemap(in) Name *GENERIC end */ %} // This would never be done in real code, it is just a test of what madness can be done. // Note that the special variable substitutions $*1_type, $descriptor etc are for NameWrap // even when used within the Name typemap via $typemap. I can't think of any useful use cases // for this behaviour in the C/C++ typemaps, but it is possible. %typemap(in) NameWrap *NAMEWRAP ($*1_type temp) %{ /*%typemap(in) NameWrap *NAMEWRAP start */ temp = $*1_ltype("$descriptor"); (void)$input; $1 = temp.getNamePtr(); /*%typemap(in) NameWrap *NAMEWRAP end */ %} // check $descriptor gets expanded properly when used in a fragment %fragment("nameDescriptor", "header") %{ /*%fragment("getNameDescriptor", "header") start */ static const char *nameDescriptor = "$descriptor(Name)"; /*%fragment("getNameDescriptor", "header") end */ %} ////////////////////////////////////////////////////////////////////////////////////// // This should use Name *GENERIC typemap which ignores passed in Name * and instead uses a newly a newly constructed Name // held in a typemap variable with name="$specialname" %typemap(in) Name *jack { // %typemap(in) Name *jack start $typemap(in, Name *GENERIC) // %typemap(in) Name *jack end } // as above, but also perform variable substitution %typemap(in) Name *jill { // %typemap(in) Name *jill start $typemap(in, Name *GENERIC, specialname=jilly) // %typemap(in) Name *jill end } %typemap(in) Name *mary { // %typemap(in) Name *mary start $typemap(in, NameWrap *NAMEWRAP) // %typemap(in) Name *mary end } %typemap(in, fragment="nameDescriptor") Name *james (Name temp) { // %typemap(in) Name *james start temp = Name(nameDescriptor); (void)$input; $1 = &temp; // %typemap(in) Name *james end } %inline %{ const char * testFred(Name *fred) { return fred->getName(); } const char * testJack(Name *jack) { return jack->getName(); } const char * testJill(Name *jill) { return jill->getName(); } const char * testMary(Name *mary) { return mary->getName(); } const char * testJames(Name *james) { return james->getName(); } %} ////////////////////////////////////////////////////////////////////////////////////// // Multi-arg typemap lookup // One would never do something like this in reality, it just checks $typemap with multi-arg typemaps %typemap(in) (Name *multiname, int num)($*1_type temp_name, $2_ltype temp_count) %{ /*%typemap(in) (Name *multiname, int num) start */ temp_name = $*1_ltype("multiname num"); temp_count = (int)strlen(temp_name.getNamePtr()->getName()); (void)$input; $1 = temp_name.getNamePtr(); $2 = temp_count + 100; /*%typemap(in) (Name *multiname, int num) end */ %} %typemap(in) (Name *jim, int count) { // %typemap(in) Name *jim start $typemap(in, (Name *multiname, int num)) // %typemap(in) Name *jim end } %inline %{ const char * testJim(Name *jim, int count) { if (count != (int)strlen(jim->getNamePtr()->getName()) + 100) return "size check failed"; else return jim->getName(); } %} ////////////////////////////////////////////////////////////////////////////////////// // Template types with more than one template parameter // check $1 and $input get expanded properly when used from $typemap() %typemap(in) Space::Pair PAIR_INT_BOOL ($1_type temp) %{ /*%typemap(in) Name *GENERIC start */ temp = Space::Pair(123, true); (void)$input; $1 = ($1_ltype)temp; /*%typemap(in) Name *GENERIC end */ %} %typemap(in) Space::Pair john { // %typemap(in) Name *john start $typemap(in, Space::Pair PAIR_INT_BOOL) // %typemap(in) Name *john end } %inline %{ namespace Space { template struct Pair { Pair(T1 f, T2 s) : first(f), second(s) {} Pair() {} T1 first; T2 second; }; int testJohn(Space::Pair john) { return john.first; } } %} %template(PairIntBool) Space::Pair; ////////////////////////////////////////////////////////////////////////////////////// // A real use case for $typemap #if defined(SWIGCSHARP) %typemap(cscode) Space::RenameMe %{ public static NewName factory(System.String s) { //below should expand to: //return new NewName( new Name(s) ); return new $typemap(cstype, Space::RenameMe)( new $typemap(cstype, Name)(s) ); } %} #elif defined(SWIGJAVA) %typemap(javacode) Space::RenameMe %{ public static NewName factory(String s) { //below should expand to: //return new NewName( new Name(s) ); return new $typemap(jstype, Space::RenameMe)( new $typemap(jstype, Name)(s) ); } %} #elif defined(SWIGD) #if (SWIG_D_VERSION == 1) %typemap(dcode) Space::RenameMe %{ public static NewName factory(char[] s) { return new $typemap(dtype, Space::RenameMe)( new $typemap(dtype, Name)(s) ); } %} #else %typemap(dcode) Space::RenameMe %{ public static NewName factory(string s) { return new $typemap(dtype, Space::RenameMe)( new $typemap(dtype, Name)(s) ); } %} #endif #endif %rename(NewName) Space::RenameMe; %inline %{ namespace Space { struct RenameMe { RenameMe(Name n) : storedName(n) {} Name getStoredName() { return storedName; } private: Name storedName; }; } %}