From: Ben A. <ba...@da...> - 2007-05-16 21:23:09
|
Hi, I'm writing a new language module (based initially on the java.cxx module), and I'm trying to figure out how while processing I should get from the enum values (e.g. Apple) to the fully qualified c++ name foo::bar::Apple. Clearly swig has enough info to do this, based on dumping the parse info, but I haven't quite grokked how we arrive at fully qualified C++ enum elements and class names in the generated *_wrap.cxx files. More generally, is there an active wiki anywhere that describes, even partially and outdatedly, the patterns behind how things *should* be done in a Language implementation and its associated typemaps? The initial "well just copy and modify" only takes one so far... thanks, Ben Allan |
From: William S F. <ws...@fu...> - 2007-05-16 22:06:41
|
Ben Allan wrote: > Hi, > > I'm writing a new language module (based initially on the java.cxx > module), and I'm trying to figure out how while processing > I should get from the enum values (e.g. Apple) to the fully qualified > c++ name foo::bar::Apple. > > Clearly swig has enough info to do this, based on dumping the parse > info, but I haven't quite grokked how we arrive at fully qualified > C++ enum elements and class names in the generated *_wrap.cxx files. > > More generally, is there an active wiki anywhere that describes, > even partially and outdatedly, the patterns behind how > things *should* be done in a Language implementation and its > associated typemaps? The initial "well just copy and modify" only > takes one so far... > The fully qualified name is passed around in the Node, or parent Node. Wherever you need this information, you can see what attributes are available by adding in a debug statement: Swig_print_node(n); William PS What language are you looking at implementing? |
From: Ben A. <ba...@da...> - 2007-05-16 22:21:34
|
Thanks for the tip. Big differences between -dump_parse_top and -dump_top -- forgot to check there. I'm looking into sidl/babel (which is rather javalike). thanks, Ben On Wed, May 16, 2007 at 11:07:48PM +0100, William S Fulton wrote: > Ben Allan wrote: > > Hi, > > > > I'm writing a new language module (based initially on the java.cxx > > module), and I'm trying to figure out how while processing > > I should get from the enum values (e.g. Apple) to the fully qualified > > c++ name foo::bar::Apple. > > > > Clearly swig has enough info to do this, based on dumping the parse > > info, but I haven't quite grokked how we arrive at fully qualified > > C++ enum elements and class names in the generated *_wrap.cxx files. > > > > More generally, is there an active wiki anywhere that describes, > > even partially and outdatedly, the patterns behind how > > things *should* be done in a Language implementation and its > > associated typemaps? The initial "well just copy and modify" only > > takes one so far... > > > > The fully qualified name is passed around in the Node, or parent Node. > Wherever you need this information, you can see what attributes are > available by adding in a debug statement: > > Swig_print_node(n); > > William > > PS What language are you looking at implementing? |
From: Ben A. <ba...@da...> - 2007-06-03 21:18:58
|
I've run into an odd thing about the language i'm binding which leaves me a puzzle about how best to solve the problem. At the heart of the issue is that the language i'm binding does not allow _ in simple identifiers. Obviously as C/C++ does allow _ in simple identifiers, this results in a minor aesthetic problem, but cest la vie. The technical problem seems to come down to SwigType_manglestr from Source/Swig/stype.c where !isalnum gets mapped to _. I'd like to reach a solution which allows a binding to redefine which function gets dispatched to in SwigType_manglestr. Obviously changes to SwigType_manglestr_default are out of the question, since many bindings depend on it remaining what it is. It occurs to me that one could do something like: static String *(*SwigType_manglestr)(SwigType *); String *SwigType_manglestr(SwigType *s) { return Swig_mangler(s); } /* signature type for mangler functions. */ typedef String *(*manglertype)(SwigType *); String *SwigType_manglestr_default(SwigType *s) { ... as is } /* private function pointer to mangler */ static manglertype Swig_mangler = SwigType_manglestr_default; /* sets the mangler used and returns the old one it replaces, or if mangler given is null, returns the mangler currently in effect. */ manglertype Swig_setMangler(manglertype mangler) { manglertype old = Swig_mangler; if (f==NULL) return Swig_mangler; Swig_mangler = mangler; return old; } String *SwigType_manglestr(String *s) { return Swig_mangler(s); } Here the net effect is: one new function in ./Source/Swig/swig.h one static variable in ./Source/Swig/stype.c and the ability of a binding to override the mangler without rewriting any existing code. Thoughts? Unpublished plans for a total refactoring of mangling that makes this irrelevant? If it's a reasonable change, I'd like to either check it in or send a patch someone can apply if cut&pasting from this email isn't adequate. thanks, Ben |
From: William S F. <ws...@fu...> - 2007-06-04 19:45:25
|
Ben Allan wrote: > I've run into an odd thing about the language i'm binding which > leaves me a puzzle about how best to solve the problem. > At the heart of the issue is that the language i'm binding > does not allow _ in simple identifiers. > > Obviously as C/C++ does allow _ in simple identifiers, > this results in a minor aesthetic problem, but cest la vie. > > The technical problem seems to come down to > SwigType_manglestr from > Source/Swig/stype.c > where !isalnum gets mapped to _. > > I'd like to reach a solution which allows a binding > to redefine which function gets dispatched to in > SwigType_manglestr. Obviously changes to > SwigType_manglestr_default are out of the question, since > many bindings depend on it remaining what it is. > It occurs to me that one could do something like: > > static String *(*SwigType_manglestr)(SwigType *); > String *SwigType_manglestr(SwigType *s) { > return Swig_mangler(s); > } > > /* signature type for mangler functions. */ > typedef String *(*manglertype)(SwigType *); > > String *SwigType_manglestr_default(SwigType *s) { > ... as is > } > > /* private function pointer to mangler */ > static manglertype Swig_mangler = SwigType_manglestr_default; > > /* sets the mangler used and returns the old one it replaces, > or if mangler given is null, returns the mangler currently in effect. > */ > manglertype Swig_setMangler(manglertype mangler) { > manglertype old = Swig_mangler; > if (f==NULL) return Swig_mangler; > Swig_mangler = mangler; > return old; > } > > String *SwigType_manglestr(String *s) { > return Swig_mangler(s); > } > > > Here the net effect is: > one new function in ./Source/Swig/swig.h > one static variable in ./Source/Swig/stype.c > and the ability of a binding to override the mangler > without rewriting any existing code. > > Thoughts? > Unpublished plans for a total refactoring of mangling that makes > this irrelevant? > > If it's a reasonable change, I'd like to either check it in > or send a patch someone can apply if cut&pasting from this > email isn't adequate. > Looks fine to me. There are no plans to refactor mangling that I know of. Can you send a patch and I'll apply it. William |
From: Ben A. <ba...@da...> - 2007-06-04 20:19:52
|
Great. will kick the tires a bit further on the version of the patch i'm running and then send it in. You prefer email or posting on some tracker somewhere for patches? thanks, Ben On Mon, Jun 04, 2007 at 08:46:30PM +0100, William S Fulton wrote: > Ben Allan wrote: > > I've run into an odd thing about the language i'm binding which > > leaves me a puzzle about how best to solve the problem. > > At the heart of the issue is that the language i'm binding > > does not allow _ in simple identifiers. > > > > Obviously as C/C++ does allow _ in simple identifiers, > > this results in a minor aesthetic problem, but cest la vie. > > > > The technical problem seems to come down to > > SwigType_manglestr from > > Source/Swig/stype.c > > where !isalnum gets mapped to _. > > > > I'd like to reach a solution which allows a binding > > to redefine which function gets dispatched to in > > SwigType_manglestr. Obviously changes to > > SwigType_manglestr_default are out of the question, since > > many bindings depend on it remaining what it is. > > It occurs to me that one could do something like: > > > > static String *(*SwigType_manglestr)(SwigType *); > > String *SwigType_manglestr(SwigType *s) { > > return Swig_mangler(s); > > } > > > > /* signature type for mangler functions. */ > > typedef String *(*manglertype)(SwigType *); > > > > String *SwigType_manglestr_default(SwigType *s) { > > ... as is > > } > > > > /* private function pointer to mangler */ > > static manglertype Swig_mangler = SwigType_manglestr_default; > > > > /* sets the mangler used and returns the old one it replaces, > > or if mangler given is null, returns the mangler currently in effect. > > */ > > manglertype Swig_setMangler(manglertype mangler) { > > manglertype old = Swig_mangler; > > if (f==NULL) return Swig_mangler; > > Swig_mangler = mangler; > > return old; > > } > > > > String *SwigType_manglestr(String *s) { > > return Swig_mangler(s); > > } > > > > > > Here the net effect is: > > one new function in ./Source/Swig/swig.h > > one static variable in ./Source/Swig/stype.c > > and the ability of a binding to override the mangler > > without rewriting any existing code. > > > > Thoughts? > > Unpublished plans for a total refactoring of mangling that makes > > this irrelevant? > > > > If it's a reasonable change, I'd like to either check it in > > or send a patch someone can apply if cut&pasting from this > > email isn't adequate. > > > Looks fine to me. There are no plans to refactor mangling that I know > of. Can you send a patch and I'll apply it. > > William |
From: William S F. <ws...@fu...> - 2007-06-04 20:33:12
|
Ben Allan wrote: > Great. will kick the tires a bit further on the version of the > patch i'm running and then send it in. > You prefer email or posting on some tracker somewhere for patches? > Patch posted to the mailing list as attached file is fine. Also please check out the top/bottom posting etiquette for future reference - http://www.swig.org/mail.html#top_bottom_posting. Thanks William |
From: Ben A. <ba...@da...> - 2007-06-06 17:59:59
|
Hi again, Has there been any progress on the subject line item in recent years? http://sourceforge.net/tracker/index.php?func=detail&aid=539872&group_id=1645&atid=351645 I see it popped up in the wiki in the google soc ideas section; were there any takers? I could *really* use the capability of pure virtual base classes being tagged for easy alternate processing. Perhaps there's stuff in the core c++ type analysis already that i've simply overlooked because I'm mostly following the java binding to develop my own binding. Rephrasing: I need this feature so badly that i'm willing to contribute the coding effort to get it if someone with a bit more perspective on how things should (not) be done in the swig core is willing to provide some guidance. I would think for starters one would need to: a) update the c++ processing to mark the pvb classes as interfaces b) add an interfaceHandler method set in Dispatcher. c) implement the default interfaceHandler methods in Language to simply redispatch to classHandler. If a language binding does not support 'interface' java style, (as most don't), they wouldn't change from current code. If a language does support the interface notion, it simply overrides the interface related methods on Language. We may discover the details of (b,c) are smaller than I expect and could be merged into classHandler without making it an unmaintainable mess, but it's already a little hairy as-is. And of course I haven't looked too hard yet for subtle interactions with the directors code that this might entail. thoughts? people already doing it? Ben Allan |
From: Brendan D. <bre...@al...> - 2007-06-07 07:21:22
Attachments:
brendand.vcf
|
Ben Allan wrote: > Hi again, > > Has there been any progress on the subject line item in recent years? > http://sourceforge.net/tracker/index.php?func=detail&aid=539872&group_id=1645&atid=351645 > I see it popped up in the wiki in the google soc ideas > section; were there any takers? > I could *really* use the capability of pure virtual base > classes being tagged for easy alternate processing. > Perhaps there's stuff in the core c++ type analysis already that i've > simply overlooked because I'm mostly following the java binding to > develop my own binding. > > Rephrasing: I need this feature so badly that i'm willing to contribute > the coding effort to get it if someone with a bit more perspective > on how things should (not) be done in the swig core > is willing to provide some guidance. > > I would think for starters one would need to: > a) update the c++ processing to mark the pvb classes as interfaces > b) add an interfaceHandler method set in Dispatcher. > c) implement the default interfaceHandler methods in Language to simply > redispatch to classHandler. If a language binding does not support > 'interface' java style, (as most don't), they wouldn't change from > current code. If a language does support the interface notion, it > simply overrides the interface related methods on Language. > > We may discover the details of (b,c) are smaller than I expect > and could be merged into classHandler without making it an > unmaintainable mess, but it's already a little hairy as-is. > And of course I haven't looked too hard yet for subtle interactions > with the directors code that this might entail. > > thoughts? people already doing it? > Hi Allen I too would be very interested in helping out with this and would like to see it Brendan > Ben Allan > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by DB2 Express > Download DB2 Express C - the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ > _______________________________________________ > Swig-devel mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-devel > |
From: John L. <jl...@ma...> - 2007-06-04 21:19:06
|
On 06/03/2007 04:17 PM, Ben Allan wrote: > I've run into an odd thing about the language i'm binding which > leaves me a puzzle about how best to solve the problem. > At the heart of the issue is that the language i'm binding > does not allow _ in simple identifiers. > > Obviously as C/C++ does allow _ in simple identifiers, > this results in a minor aesthetic problem, but cest la vie. > The chicken and guile modules rename _ to - in identifiers. I suggest you check out how they do it. Just search in Source/Modules/chicken.cxx and Source/Modules/guile.cxx for code like Replaceall( ... , "_", "-"); Basically, we leave the names inside swig with the _, and just change the function name right before it is inserted into the wrapper file. I would be very hesitant to change anything with the type mangling. John |
From: Ben A. <ba...@da...> - 2007-06-04 22:02:24
|
On Mon, Jun 04, 2007 at 04:18:19PM -0500, John Lenz wrote: > On 06/03/2007 04:17 PM, Ben Allan wrote: > > I've run into an odd thing about the language i'm binding which > > leaves me a puzzle about how best to solve the problem. > > At the heart of the issue is that the language i'm binding > > does not allow _ in simple identifiers. > > > > Obviously as C/C++ does allow _ in simple identifiers, > > this results in a minor aesthetic problem, but cest la vie. > > > > The chicken and guile modules rename _ to - in identifiers. I suggest > you check out how they do it. Just search in Source/Modules/chicken.cxx > and Source/Modules/guile.cxx for code like > > Replaceall( ... , "_", "-"); > > Basically, we leave the names inside swig with the _, and just change > the function name right before it is inserted into the wrapper file. > > I would be very hesitant to change anything with the type mangling. > > John So I went well down the replaceall and equivalent routes and for the language being bound it just doesn't work. The bound language allows (indeed requires) _ between nesting levels in package/namespace names, bans _ altogther within class/interface/type names, and allows _ almost arbitrarily within member (function, variable) names. The proposed solution touches nothing in the core behavior of swig or any existing binding. It just exposes a knob that new bindings for mangle-quirky languages can use if they go out of their way. If someone wants to use it for an older binding, more power to'em. One option I have in creating a patch for this is whether to expose the SwigType_manglestr_default function and its alternatives (SwigType_manglestr_nounderbar) in swig.h. I would prefer to expose them, but I can make my binding work without exposing those functions. Feedback on that welcome. My argument for exposing them in swig.h has two simple components: a) new binding authors will find them easily and in the most appropriate place. b) all the alternative implementations of SwigType_manglestr can be kept in stype.c, where (after the first two or three) most likely anyone thinking of creating a new mangling will find the equivalent already existing. Ben |
From: Ben A. <ba...@da...> - 2007-06-06 19:11:41
|
Here's a patch which introduces alternative mangler ability without requiring changes to existing bindings. As mentioned in another posting, it could also work without exposing extern String *SwigType_manglestr_default(SwigType *s); extern String *SwigType_manglestr_nounderscore(SwigType *s); but I would prefer to expose all the manglings available if possible. In the 'hidden' case, the SwigType_manglestr_nounderscore would not be put in stype.c but instead off somewhere in my binding. Ben Index: Source/Swig/stype.c =================================================================== --- Source/Swig/stype.c (revision 9805) +++ Source/Swig/stype.c (working copy) @@ -983,9 +983,99 @@ else if (*c == ')') *c = 'F'; else if (!isalnum((int) *c)) + *c = '_'; + c++; + } + Append(result, base); + Insert(result, 0, "_"); + Delete(lt); + Delete(base); + if (ss) + Delete(ss); + return result; +} + +/* A new mangling for bindings where simple typenames disallow underscore +and namespaces are separated by '_' or (with simple substitutions) '.' . +. +The handling for c++ that differs from the default mangler is: +':' --> 8 ( fat colon ) +' ' --> B ( 'blank', capitalized) +'_' --> L ( visual nearest neighbor in [a-zA-Z]) +!isalnum((int) *c) --> '9' ( seems the least bad replacement, for various reasons ) +Other aspects of leaf type handling that are currently embedded +in the swig core (like prefixing with SWIGTYPE_p_) +seem to be easily handled by Replacealls. +Based on ISO standards, there is no concern that an identifier morphed +will start with 8 or 9. + */ +String *SwigType_manglestr_nounderscore(SwigType *s) { + char *c; + String *result = 0; + String *base = 0; + SwigType *lt; + SwigType *sr = SwigType_typedef_qualified(s); + SwigType *ss = SwigType_typedef_resolve_all(sr); + + s = ss; + + if (SwigType_istemplate(ss)) { + SwigType *ty = Swig_symbol_template_deftype(ss, 0); + Delete(ss); + ss = ty; + s = ss; + } + Delete(sr); + + lt = SwigType_ltype(s); + result = SwigType_prefix(lt); + base = SwigType_base(lt); + + c = Char(result); + while (*c) { + if (!isalnum((int) *c)) *c = '_'; c++; } + if (SwigType_istemplate(base)) { + String *b = SwigType_namestr(base); + Delete(base); + base = b; + } + + Replace(base, "struct ", "", DOH_REPLACE_ANY); /* This might be problematic */ + Replace(base, "class ", "", DOH_REPLACE_ANY); + Replace(base, "union ", "", DOH_REPLACE_ANY); + Replace(base, "enum ", "", DOH_REPLACE_ANY); + + c = Char(base); + while (*c) { + if (*c == '<') + *c = 'T'; + else if (*c == '>') + *c = 't'; + else if (*c == '*') + *c = 'p'; + else if (*c == '[') + *c = 'a'; + else if (*c == ']') + *c = 'A'; + else if (*c == '&') + *c = 'R'; + else if (*c == '(') + *c = 'f'; + else if (*c == ')') + *c = 'F'; + else if (*c == '_') + *c = 'L'; + else if (*c == ':') + *c = '8'; + else if (*c == ' ') + *c = 'B'; + else if (!isalnum((int) *c)) + *c = '9'; + c++; + } Append(result, base); Insert(result, 0, "_"); Delete(lt); @@ -995,8 +1085,28 @@ return result; } +static Swig_manglertype Swig_mangler = SwigType_manglestr_default; + +/* ----------------------------------------------------------------------------- + * SwigType_set_mangler() + * + * Replaces the current mangler function with a new one, returning the + * old one to the caller. + * Design note: Calling with NULL changes nothing but gives access to the + * current mangler. The other alternative (if NULL, reset to default) does + * not allow the caller to as easily handle obscure cases where a binding + * may want to push/popd handlers on the stack midstream. + * A separate get_mangler could be provided if desired on aesthetic grounds. + * ----------------------------------------------------------------------------- */ +Swig_manglertype SwigType_set_mangler(Swig_manglertype mangler) { + Swig_manglertype old = Swig_mangler; + if (mangler==NULL) return Swig_mangler; + Swig_mangler = mangler; + return old; +} + String *SwigType_manglestr(SwigType *s) { - return SwigType_manglestr_default(s); + return Swig_mangler(s); } /* ----------------------------------------------------------------------------- Index: Source/Swig/swig.h =================================================================== --- Source/Swig/swig.h (revision 9805) +++ Source/Swig/swig.h (working copy) @@ -132,7 +132,13 @@ extern String *SwigType_lstr(SwigType *s, const String_or_char *id); extern String *SwigType_rcaststr(SwigType *s, const String_or_char *id); extern String *SwigType_lcaststr(SwigType *s, const String_or_char *id); + + typedef String *(*Swig_manglertype)(SwigType *); + extern Swig_manglertype SwigType_set_mangler(Swig_manglertype mangler); + extern String *SwigType_manglestr_default(SwigType *s); + extern String *SwigType_manglestr_nounderscore(SwigType *s); extern String *SwigType_manglestr(SwigType *t); + extern SwigType *SwigType_ltype(SwigType *t); extern int SwigType_ispointer(SwigType *t); extern int SwigType_ispointer_return(SwigType *t); |
From: Ben A. <ba...@da...> - 2007-06-08 16:53:24
Attachments:
Source_Swig.diff
|
Here's a revised patch which introduces alternative mangler ability without requiring changes to existing bindings. This separates getter and setter. Ben |
From: John L. <jl...@ma...> - 2007-06-06 21:13:09
|
On 06/06/2007 02:10 PM, Ben Allan wrote: > Here's a patch which introduces alternative mangler ability > without requiring changes to existing bindings. > As mentioned in another posting, it could also work without exposing > extern String *SwigType_manglestr_default(SwigType *s); > extern String *SwigType_manglestr_nounderscore(SwigType *s); > but I would prefer to expose all the manglings available if possible. Yeah, I think it is fine to expose the manglers > In the 'hidden' case, the SwigType_manglestr_nounderscore > would not be put in stype.c but instead off somewhere in my binding. No, they should be shared if possible. > +static Swig_manglertype Swig_mangler = SwigType_manglestr_default; > + > +/* ----------------------------------------------------------------------------- > + * SwigType_set_mangler() > + * > + * Replaces the current mangler function with a new one, returning the > + * old one to the caller. > + * Design note: Calling with NULL changes nothing but gives access to the > + * current mangler. The other alternative (if NULL, reset to default) does > + * not allow the caller to as easily handle obscure cases where a binding > + * may want to push/popd handlers on the stack midstream. > + * A separate get_mangler could be provided if desired on aesthetic grounds. > + * ----------------------------------------------------------------------------- */ I would rather see a separate get_mangler. Makes the code (in the module) clearer what is happening. And we don't really have a mandate to keep the exported functions small... the swig core API can get as big as it needs to. > +Swig_manglertype SwigType_set_mangler(Swig_manglertype mangler) { > + Swig_manglertype old = Swig_mangler; > + if (mangler==NULL) return Swig_mangler; > + Swig_mangler = mangler; > + return old; > +} Other than that, this code looks fine. John |
From: Ben A. <ba...@da...> - 2007-06-06 22:30:46
|
On Wed, Jun 06, 2007 at 04:12:10PM -0500, John Lenz wrote: > I would rather see a separate get_mangler. Makes the code (in the That's fine by me. Is it preferred that I resubmit an updated patch with the simpler functions, or will the patching person add getmangler on the fly? I'm happy with either option. I just don't know what the habits are in this project. thanks, Ben |
From: William S F. <ws...@fu...> - 2007-06-07 22:35:57
|
Ben Allan <baallan <at> dancer.ca.sandia.gov> writes: > > > On Wed, Jun 06, 2007 at 04:12:10PM -0500, John Lenz wrote: > > I would rather see a separate get_mangler. Makes the code (in the > > That's fine by me. Is it preferred that I resubmit an updated patch > with the simpler functions, or will the patching > person add getmangler on the fly? I'm happy with either option. > I just don't know what the habits are in this project. > Post the new patch as an attachment to the mailing list should be fine. William |
From: Ben A. <ba...@da...> - 2007-06-08 22:55:24
|
Hi, I see SwigType_type appears to be rather deprecated (and rather ugly...). Is the result of Getattr(x,"nodeType") a closed set that could be made into an enum, or is it in principle growing over the development of swig? I find myself (in spite of several attempts to find some other way with typemaps) wanting to write the moral equivalent of: switch (nodeType(n)) { case class: break; case enum: break; case primitive: break; default: } where the actions are omitted, of course. I can do it with strings-- just wondering if there's a better way I overlooked. Can someone smack me and inculcate the proper zen approach to node types? (as usual, this is part of a thorny problem in arg type and return type processing). thanks, Ben |
From: William S F. <ws...@fu...> - 2007-06-07 22:48:59
|
Brendan Donovan <brendand <at> al.com.au> writes: > > > Ben Allan wrote: > > Hi again, > > > > Has there been any progress on the subject line item in recent years? > > http://sourceforge.net/tracker/index.php?func=detail&aid=539872&group_id=1645&atid=351645 > > I see it popped up in the wiki in the google soc ideas > > section; were there any takers? > > I could *really* use the capability of pure virtual base > > classes being tagged for easy alternate processing. > > Perhaps there's stuff in the core c++ type analysis already that i've > > simply overlooked because I'm mostly following the java binding to > > develop my own binding. > > > > Rephrasing: I need this feature so badly that i'm willing to contribute > > the coding effort to get it if someone with a bit more perspective > > on how things should (not) be done in the swig core > > is willing to provide some guidance. > > > > I would think for starters one would need to: > > a) update the c++ processing to mark the pvb classes as interfaces > > b) add an interfaceHandler method set in Dispatcher. > > c) implement the default interfaceHandler methods in Language to simply > > redispatch to classHandler. If a language binding does not support > > 'interface' java style, (as most don't), they wouldn't change from > > current code. If a language does support the interface notion, it > > simply overrides the interface related methods on Language. > > > > We may discover the details of (b,c) are smaller than I expect > > and could be merged into classHandler without making it an > > unmaintainable mess, but it's already a little hairy as-is. > > And of course I haven't looked too hard yet for subtle interactions > > with the directors code that this might entail. > > > > thoughts? people already doing it? > > > Hi Allen > I too would be very interested in helping out with this and would like > to see it > I put the Google SOC items on the wiki, but there is no work happening on this feature as far as I know. The approach you outline is pretty much the way in which I'd tackle it. However, I'd also enable it using a user defined %feature as generating interfaces by default is likely to lead to uncompilable Java code. Consider wrapping this c++ code: class Foo; // an abstract base class / interface Foo* f(); The proxy function for f() will not compile as a Foo instance must be created in Java without any knowledge as to what derived type Foo really is. Attempting to instantiate the Foo Java interface will fail to compile. If you tackle coding this up, might I suggest you provide a patch to the Java module so that I can check it with a known working module before porting it to your own module. William |
From: Ben A. <ba...@da...> - 2007-06-08 00:51:48
|
Hi William, On Thu, Jun 07, 2007 at 10:48:33PM +0000, William S Fulton wrote: > Brendan Donovan <brendand <at> al.com.au> writes: > > > > > > > Ben Allan wrote: > > > Hi again, > > > > > > Has there been any progress on the subject line item in recent years? > > > > http://sourceforge.net/tracker/index.php?func=detail&aid=539872&group_id=1645&atid=351645 > > > I see it popped up in the wiki in the google soc ideas > > > section; were there any takers? > > > I could *really* use the capability of pure virtual base > > > classes being tagged for easy alternate processing. > > > Perhaps there's stuff in the core c++ type analysis already that i've > > > simply overlooked because I'm mostly following the java binding to > > > develop my own binding. > > > > > > Rephrasing: I need this feature so badly that i'm willing to contribute > > > the coding effort to get it if someone with a bit more perspective > > > on how things should (not) be done in the swig core > > > is willing to provide some guidance. > > > > > > I would think for starters one would need to: > > > a) update the c++ processing to mark the pvb classes as interfaces > > > b) add an interfaceHandler method set in Dispatcher. > > > c) implement the default interfaceHandler methods in Language to simply > > > redispatch to classHandler. If a language binding does not support > > > 'interface' java style, (as most don't), they wouldn't change from > > > current code. If a language does support the interface notion, it > > > simply overrides the interface related methods on Language. > > > > > > We may discover the details of (b,c) are smaller than I expect > > > and could be merged into classHandler without making it an > > > unmaintainable mess, but it's already a little hairy as-is. > > > And of course I haven't looked too hard yet for subtle interactions > > > with the directors code that this might entail. > > > > > > thoughts? people already doing it? > > > > > Hi Allen > > I too would be very interested in helping out with this and would like > > to see it > > > > I put the Google SOC items on the wiki, but there is no work happening on this > feature as far as I know. > > The approach you outline is pretty much the way in which I'd tackle it. However, > I'd also enable it using a user defined %feature as generating interfaces by > default is likely to lead to uncompilable Java code. Consider wrapping this c++ > code: > > class Foo; // an abstract base class / interface > > Foo* f(); > > The proxy function for f() will not compile as a Foo instance must be created in > Java without any knowledge as to what derived type Foo really is. Attempting to > instantiate the Foo Java interface will fail to compile. I'm not clear how this is a problem. Is there not always a trivial wrapper/director in a Java binding (or easily addable): package $MODULE; public interface Foo { ... } class SWIG_Foo implements Foo {...} // can wrap any C++ Foo *. Would such an approach violate some existing property of the java binding or some expectation of its existing users? Where I would think there will be a problem of mapping (just a lot of ugly code, not conceptual) is in multiple inheritance of pvb classes being mapped properly so casting works as expected in java. Is casting a requirement for a 1.0 version of this feature, or would it be acceptable that the Foo wrapper is not castable to other bases in java in a first release? > If you tackle coding this up, might I suggest you provide a patch to the Java > module so that I can check it with a known working module before porting it to > your own module. Java-first seems like the right approach. I'll start trying to decode what goes on inside the c++ processing to add detection pure virtual bases. While i'm doing that, could you make a suggestion what syntax you might expect to see for declaring and for using a feature to tag a pvb class to be treated as an interface? It seems you are suggesting that the user may not want all (or any?) pvb classes mapped to interfaces. thanks, Ben |
From: William S F. <ws...@fu...> - 2007-06-11 21:21:43
|
Ben Allan <baallan <at> dancer.ca.sandia.gov> writes: > > Hi William, > > On Thu, Jun 07, 2007 at 10:48:33PM +0000, William S Fulton wrote: > > Brendan Donovan <brendand <at> al.com.au> writes: > > > > I put the Google SOC items on the wiki, but there is no work happening on > > this > > feature as far as I know. > > > > The approach you outline is pretty much the way in which I'd tackle it. > > However, > > I'd also enable it using a user defined %feature as generating interfaces by > > default is likely to lead to uncompilable Java code. Consider wrapping this > > c++ > > code: > > > > class Foo; // an abstract base class / interface > > > > Foo* f(); > > > > The proxy function for f() will not compile as a Foo instance must be > > created in > > Java without any knowledge as to what derived type Foo really is. Attempting > > to > > instantiate the Foo Java interface will fail to compile. > > I'm not clear how this is a problem. Is there not always a trivial > wrapper/director in a Java binding (or easily addable): > > package $MODULE; > public interface Foo { ... } > class SWIG_Foo implements Foo {...} // can wrap any C++ Foo *. > > Would such an approach violate some existing property of the > java binding or some expectation of its existing users? > Where I would think there will be a problem of mapping (just a lot of > ugly code, not conceptual) is in multiple inheritance of pvb classes > being mapped properly so casting works as expected in java. > Is casting a requirement for a 1.0 version of this feature, or > would it be acceptable that the Foo wrapper is not castable to other > bases in java in a first release? > The Java interface would be fine: public interface Foo { ... public void bar(); } But how do you wrap the f() method? Currently it is wrapped as: public static Foo f() { long cPtr = exampleJNI.f(); return (cPtr == 0) ? null : new Foo(cPtr, false); } That won't compile as you can't instantiate an interface. I can't find a definition of pvb. Can you please explain your casting question, is it Java or C++ casts you are talking about and is this a SWIG generated cast or a user added cast? William |
From: Ben A. <ba...@da...> - 2007-06-11 23:10:34
|
On Mon, Jun 11, 2007 at 09:21:13PM +0000, William S Fulton wrote: > Ben Allan <baallan <at> dancer.ca.sandia.gov> writes: > > > > > Hi William, > > > > On Thu, Jun 07, 2007 at 10:48:33PM +0000, William S Fulton wrote: > > > Brendan Donovan <brendand <at> al.com.au> writes: > > > > > > > I put the Google SOC items on the wiki, but there is no work happening on > > > this > > > feature as far as I know. > > > > > > The approach you outline is pretty much the way in which I'd tackle it. > > > However, > > > I'd also enable it using a user defined %feature as generating interfaces by > > > default is likely to lead to uncompilable Java code. Consider wrapping this > > > c++ > > > code: > > > > > > class Foo; // an abstract base class / interface > > > > > > Foo* f(); > > > > > > The proxy function for f() will not compile as a Foo instance must be > > > created in > > > Java without any knowledge as to what derived type Foo really is. Attempting > > > to > > > instantiate the Foo Java interface will fail to compile. > > > > I'm not clear how this is a problem. Is there not always a trivial > > wrapper/director in a Java binding (or easily addable): > > > > package $MODULE; > > public interface Foo { ... } > > class SWIG_Foo implements Foo {...} // can wrap any C++ Foo *. > > > > > Would such an approach violate some existing property of the > > java binding or some expectation of its existing users? > > Where I would think there will be a problem of mapping (just a lot of > > ugly code, not conceptual) is in multiple inheritance of pvb classes > > being mapped properly so casting works as expected in java. > > Is casting a requirement for a 1.0 version of this feature, or > > would it be acceptable that the Foo wrapper is not castable to other > > bases in java in a first release? > > > > The Java interface would be fine: > public interface Foo { > ... > public void bar(); > } > > But how do you wrap the f() method? Currently it is wrapped as: > > public static Foo f() { > long cPtr = exampleJNI.f(); > return (cPtr == 0) ? null : new Foo(cPtr, false); > } > > That won't compile as you can't instantiate an interface. I was picturing generated code from the C++ level: mangled_f() { Foo * ptr = f(); // there is a concrete version of Foo somewhre in there. jlong cptr = (jlong)(void *)ptr; // or static_cast... JNIEquivalentOF{{{ // don't have this bit handy, but I can get it x = new SWIG_Foo(cptr, false); y = (Foo)x; return y; }}} /// that blocked above as JNIEquivalentOF might even be /// reasonably pushed up to the java layer of the wrapper. } With the accompanying java interface and proxy class SWIG_Foo. The methods on swig_foo are of course all native wrappers that redispatch to cptr. In this way, the swig_foo wrapper never needs to know what actual implementation class the c++ f() function used to instantiate the pointer to a pure virtual base returned. > I can't find a definition of pvb. Can you please explain your casting question, Sorry. (c++) pure virtual base. By which I mean (I think conventionally) C++: class X { virtual ~X(){} // virtual destructor, no constructors virtual int whatevermethod() = 0; // all functions are abstract virtual ... }; Using pv bases (pvb), one gets the java interface multiple inheritance equivalent in C++ (used on a lot of projects): class ImplementSomeThings : public virtual X, public virtual Y, public virtual Foo { ImplementSomeThings(); virtual ~ImplementSomeThings(); ... } Given a class like ImplementSomeThings, you can cast/assign a pointer to it as a Foo*, X*, or Y*. Given a java Swig_Foo class wrapping as part of the f() binding in your example, one could define additional casting functions that take a Java Foo, attempt the cast to Swig_Foo, and if successful then dive back down into jni/c++ to attempt a c++ dynamic cast to, e.g. X*, and return an X* wrapper (SWIG_X). This gets particularly desirable in the case where in c++ class Z : public virtual Foo { ... }; These functions don't look like a java cast (I don't think sun defined jni hooks for casting, did they?), but instead some sort of java signature like: static X cast_FooToX(Foo instance); The main idea being that a C++ pointer which is dynamic_cast-able to all its bases in C++, should be equivalently castable to/from those interfaces in Java. > is it Java or C++ casts you are talking about and is this a SWIG generated cast > or a user added cast? Swig has all the needed info, so i don't see why it wouldn't be the default to generate these cast operators. Without the intervening concrete (protected or package private) java class SWIG_Foo, the whole scheme collapses. Handling polymorphism in two languages makes one's head spin a little. The reference count management must be excruciatingly correct if one does not resort to using boost shared pointers down at the jni level. I think that's a dependency (boost) we'd prefer to avoid in swig, though. What have I overlooked? Does this note dovetail somehow with the directors stuff? Ben |
From: Ben A. <ba...@da...> - 2007-06-13 02:24:05
|
Here's a little patch for the sake of formatting. If append returned some sort of count of things appended this might be made faster, but given the abstractions happening, it's easier just to check len and hope someone is recomputing len every time if the string is unchanged. Index: wrapfunc.c =================================================================== --- wrapfunc.c (revision 9855) +++ wrapfunc.c (working copy) @@ -434,8 +434,11 @@ obj = va_arg(ap, void *); while (obj) { + int oldlen=Len(decl); /* suppress extra spaces around empty strings */ Append(decl, obj); - Putc(' ', decl); + if (oldlen != Len(decl)) { + Putc(' ', decl); + } obj = va_arg(ap, void *); } va_end(ap); |
From: Ben A. <ba...@da...> - 2007-06-13 03:33:17
Attachments:
patch2.diff
|
Here is a cumulative patch of the mangler function setter a whitespace improvement, and a modification to teach the core to properly compute 'cppinterface' markings on all c++ classes so that interested binding authors can check the value of cppinterface (0,1) and generate code accordingly. Also included are feature directives to let the user override cppinterface-ness in either direction and to let the user enable diagnostics wheh they expect an interface class and don't get one. This patch affects none of the existing bindings (yet) in any way. A small change to the parser is required where previously certain inheritance details were abandoned (virtualness). Putting support for cppinterface into the java binding is a much bigger job than detecting interface classes, and other binding authors might like to have this attribute to work with before a full java application of it is finished. For those that missed the prior discussion, java interface types have an (almost) exact analog in c++: pure virtual base classes inherited public virtually. This patch marks those c++ classes and lets the clever user even tell the binding generators constructive lies. An example of the c++ interface concept: // here's a base class Base1 { virtual ~Base1(){} // note: exactly this form of destructor is required. virtual void someFunc() = 0; // all member functions must be abstract to fit the java pattern. // no data members or inner classes. // If there's a C++ language lawyer in the house, please issue // rebuttal if appropriate. }; And then with several of these (Base2, Base3...) we can do: class Concrete : public virtual Base1, public virtual Base2, public virtual base3 // note: all bases must inherit both publically and virtually. { Concrete(); virtual ~Concrete(); // note: must be virtual } which is equivalent to Java doing interface Base1 { ... } interface Base2 { ... } interface Base3 { ... } class Concrete implements Base1 ,Base2, Base3 { ... } and can be directly mapped to that. When using this pattern in c++, diamond-inheritance insanities are eliminated. Enjoy, Ben Allan |
From: William S F. <ws...@fu...> - 2007-08-14 23:05:38
|
Ben Allan wrote: > Here's a little patch for the sake of formatting. > If append returned some sort of count of things appended > this might be made faster, but given the abstractions > happening, it's easier just to check len and hope someone > is recomputing len every time if the string is unchanged. > > Index: wrapfunc.c > =================================================================== > --- wrapfunc.c (revision 9855) > +++ wrapfunc.c (working copy) > @@ -434,8 +434,11 @@ > > obj = va_arg(ap, void *); > while (obj) { > + int oldlen=Len(decl); /* suppress extra spaces around empty strings */ > Append(decl, obj); > - Putc(' ', decl); > + if (oldlen != Len(decl)) { > + Putc(' ', decl); > + } > obj = va_arg(ap, void *); > } > va_end(ap); > > Ben, Can you elaborate on what this patch does, perhaps with an example of the formatting improvement? Thanks William |