|
[PATCH] assortment of problems: msg#00141programming.swig
I have been having a series of problems when trying to wrap a couple of templatized C++ classes with Perl. I have finally beaten SWIG into submission with a set of patches, all of one of which are attached to this message. The first patch, which is not attached because it is large, is John Lenz's type system patch at <http://www.cs.wisc.edu/~lenz/swig.html>. I modified it very slightly, however -- both my C++ library and Perl were using the DEBUG macro, and Lenz's patch added yet another use, so I edited the patch to use SWIG_DEBUG instead. I used this patch because it sounded like it might fix my problems. It didn't, but it still seems like a nice improvement. In fact, I think there's a pretty good chance that it ended up providing a large piece of the solution, but I haven't tried going back and applying all my other patches without it in order to find out. The second patch (SWIG-1.3.21-warnings.diff) just removes a bunch of warnings about incomplete initializers. The problem is present with or without Lenz's patch, but this patch will only apply on top of his stuff since it changes what gets initialized, while still initializing stuff in the same way. The third patch (SWIG-1.3.21-debug.diff) adds a -debug flag to SWIG to turn on template debugging (it sets the global template_debug variable). It doesn't do it in a pretty way, but I didn't really care. The fourth patch (SWIG-1.3.21-qual.diff) makes SWIG look for template name matches both without any namespace qualification (as in swig1.3.21) and with it. I had code like: namespace std { template<class T, typename A> class vector<T,A>... %define specialize_std_vector(T) template<typename A> class vector<T,A>... %enddef } . . . %template(MyFloatVec) std::vector<float, MyAllocator<float> >; That compares 'vector' with 'std::vector' and fails. If I instead say 'std::vector' within the 'namespace std' section, it fails because... I forget, and left my notes at home. But it doesn't work, and saying namespace std { std::vector } just seems redundant anyway. The fifth patch (SWIG-1.3.21-perlshadow.diff) adds a SWIG_FindType routine that searches through all swig_type_info*'s and calls a user-provided function on them, returning the first one that returns true. Then I use that in the perl*.swg files to lookup swig_type_info's for shadow class names (which are stored in ->clientdata). This is because I couldn't figure out any way of wrapping up a C++ object as a Perl shadow class SV from within C++. I could use QueryType and NewPointerObj to wrap things up as the underlying types, but then they would have no association with the shadow type. This patch requires Lenz's patch because the way you iterate through all swig_type_info*'s is different. I really should break this patch up into two patches, one of which just provides SWIG_FindType and has nothing to do with Perl, and then the Perl-specific stuff. But given my fuzzy understanding of the SWIG internals, I'm guessing it's more likely that these patches won't make any sense to people who actually know what's going on, so I'd rather not go to the effort. (But I'd be interested if someone could clean up my use of the various layers of SWIG_XXX and SWIG_Perl_XXX and SWIGIMPORT() and SWIGRUNTIME() and ...?) I am also attaching the .spec file I use to generate my SWIG RPM, since it includes these patches and also has some changes to properly build outside of the system RPM area. (The provided .spec file leaks various files into system directories.) Finally, I should note that some of this will not apply to the current CVS, because it has added some weird A vs B|C|D type equivalency searching that collides with Lenz's patch. I didn't bother to look at why it's needed, because everything is finally working for me (as far as I can tell so far!). Yes, I know I ought to be filing bugs for all of these things, but I've probably spent far too much time already struggling with this stuff. I'll try to at least put these patches into the tracker. Index: Lib/common.swg =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Lib/common.swg,v retrieving revision 1.2 diff -u -u -r1.2 common.swg --- Lib/common.swg 19 May 2004 19:12:32 -0000 1.2 +++ Lib/common.swg 19 May 2004 19:56:22 -0000 @@ -194,7 +194,7 @@ module->type_initial = type_init; module->cast_initial = cast_init; - #ifdef DEBUG + #ifdef SWIG_DEBUG printf("Loaded module\n"); for (i = 0; i < module->size; i++) { printf(" Type 0x%x: %s\n", module->types[i], module->types[i]->str); Index: Source/Modules/perl5.cxx =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Source/Modules/perl5.cxx,v retrieving revision 1.1 diff -u -u -r1.1 perl5.cxx --- Source/Modules/perl5.cxx 19 May 2004 19:11:28 -0000 1.1 +++ Source/Modules/perl5.cxx 19 May 2004 19:56:22 -0000 @@ -340,7 +340,7 @@ Printf(f_wrappers,"%s",type_table); Delete(type_table); - Printf(constant_tab,"{0}\n};\n"); + Printf(constant_tab,"{0,0,0,0,0,0}\n};\n"); Printv(f_wrappers,constant_tab,NIL); Printf(f_wrappers,"#ifdef __cplusplus\n}\n#endif\n"); @@ -350,7 +350,7 @@ Printf(f_init,"}\n"); /* Finish off tables */ - Printf(variable_tab, "{0}\n};\n"); + Printf(variable_tab, "{0,0,0,0}\n};\n"); Printv(f_wrappers,variable_tab,NIL); Printf(command_tab,"{0,0}\n};\n"); Index: Source/Swig/typesys.c =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Source/Swig/typesys.c,v retrieving revision 1.2 diff -u -u -r1.2 typesys.c --- Source/Swig/typesys.c 19 May 2004 19:12:35 -0000 1.2 +++ Source/Swig/typesys.c 19 May 2004 19:56:22 -0000 @@ -1680,9 +1680,9 @@ ckey = NewStringf("%s+%s", ei.item, ki.key); conv = Getattr(conversions,ckey); if (conv) { - Printf(cast_temp," {&_swigt_%s, %s},", ei.item, conv); + Printf(cast_temp," {&_swigt_%s, %s, 0,0},", ei.item, conv); } else { - Printf(cast_temp," {&_swigt_%s},", ei.item); + Printf(cast_temp," {&_swigt_%s, 0,0,0},", ei.item); } Delete(ckey); @@ -1690,7 +1690,7 @@ Printf(f_forward, "#define SWIGTYPE%s swig_types[%i]\n", ei.item, i); Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0};\n", ei.item, ei.item); Printf(table, " &_swigt_%s,\n", ei.item); - Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s},{0}};\n", ei.item, ei.item); + Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s,0,0,0},{0,0,0,0}};\n", ei.item, ei.item); Printf(cast_init, " _swigc_%s,\n", ei.item); i++; @@ -1698,7 +1698,7 @@ } } Delete(el); - Printf(cast,"%s{0}};\n", cast_temp); + Printf(cast,"%s{0,0,0,0}};\n", cast_temp); Delete(cast_temp); ki = Next(ki); } @@ -1706,7 +1706,7 @@ Printf(table, "};\n"); Printf(cast_init, "};\n"); Printf(f_forward,"static swig_type_info *swig_types[%i];\n", i); - Printf(f_forward,"static swig_module_info swig_module = {swig_types, %i, 0, 0};\n", i); + Printf(f_forward,"static swig_module_info swig_module = {swig_types, %i, 0, 0, 0, 0};\n", i); Printf(f_forward,"\n/* -------- TYPES TABLE (END) -------- */\n\n"); Printf(f_table,"%s\n", types); Printf(f_table,"%s\n", table); Index: Source/Modules/swigmain.cxx =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Source/Modules/swigmain.cxx,v retrieving revision 1.1 diff -u -u -r1.1 swigmain.cxx --- Source/Modules/swigmain.cxx 19 May 2004 19:11:28 -0000 1.1 +++ Source/Modules/swigmain.cxx 24 May 2004 17:15:12 -0000 @@ -51,6 +51,10 @@ Language *swig_csharp(void); } +extern "C" { + void Swig_cparse_debug_templates(int); +} + struct swig_module { const char *name; ModuleFactory fac; @@ -125,6 +129,9 @@ } else if (strcmp(argv[i],"-nolang") == 0) { dl = new Language; Swig_mark_arg(i); + } else if (strcmp(argv[i],"-debug") == 0) { + Swig_cparse_debug_templates(1); + Swig_mark_arg(i); } else if ((strcmp(argv[i],"-dnone") == 0) || (strcmp(argv[i],"-dhtml") == 0) || (strcmp(argv[i],"-dlatex") == 0) || Index: Source/CParse/templ.c =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Source/CParse/templ.c,v retrieving revision 1.1 diff -u -u -r1.1 templ.c --- Source/CParse/templ.c 19 May 2004 19:11:27 -0000 1.1 +++ Source/CParse/templ.c 24 May 2004 17:17:03 -0000 @@ -387,7 +387,7 @@ Node * Swig_cparse_template_locate(String *name, Parm *tparms) { Node *n; - String *tname, *rname = 0; + String *tname, *qualname, *rname = 0; Node *templ; List *mpartials = 0; Parm *p; @@ -415,24 +415,27 @@ /* Search for an exact specialization. Example: template<> class name<int> { ... } */ - { - if (template_debug) { - Printf(stdout," searching: '%s' (exact specialization)\n", tname); - } - n = Swig_symbol_clookup_local(tname,0); - if (n) { - Node *tn; - if (Strcmp(nodeType(n),"template") == 0) goto success; - tn = Getattr(n,"template"); - if (tn) { - n = tn; - goto success; /* Previously wrapped by a template return that */ - } - Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); - Delete(tname); - Delete(parms); - return 0; /* Found a match, but it's not a template of any kind. */ - } + if (template_debug) { + Printf(stdout," searching: '%s' (exact specialization)\n", tname); + } + n = Swig_symbol_clookup_local(tname,0); + qualname = Copy(Swig_symbol_getscopename()); + Append(qualname, "::"); + Append(qualname, tname); + if (!n) n = Swig_symbol_clookup_local(qualname,0); + if (n) { + Node *tn; + if (Strcmp(nodeType(n),"template") == 0) goto success; + tn = Getattr(n,"template"); + if (tn) { + n = tn; + goto success; /* Previously wrapped by a template return that */ + } + Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); + Delete(tname); + Delete(parms); + Delete(qualname); + return 0; /* Found a match, but it's not a template of any kind. */ } /* Search for generic template */ @@ -499,8 +502,11 @@ } if (template_debug) { Printf(stdout," searching: '%s' (partial specialization - %s)\n", ss, pi.item); + Printf(stdout," %s eq %s\n", ss, tname); + Printf(stdout," %s eq %s\n", ss, rname); + Printf(stdout," %s eq %s\n", ss, qualname); } - if ((Strcmp(ss,tname) == 0) || (Strcmp(ss,rname) == 0)) { + if ((Strcmp(ss,tname) == 0) || (Strcmp(ss,rname) == 0) || (Strcmp(ss,qualname) == 0)) { Append(mpartials,pi.item); } Delete(ss); @@ -535,6 +541,7 @@ success: Delete(tname); Delete(rname); + Delete(qualname); Delete(mpartials); if ((template_debug) && (n)) { Printf(stdout,"Node: %x\n", n); Index: Lib/common.swg =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Lib/common.swg,v retrieving revision 1.2 diff -u -u -r1.2 common.swg --- Lib/common.swg 19 May 2004 19:12:32 -0000 1.2 +++ Lib/common.swg 25 May 2004 00:15:06 -0000 @@ -90,6 +90,7 @@ SWIGIMPORT(swig_type_info *) SWIG_TypeDynamicCast(swig_type_info *, void **); SWIGIMPORT(const char *) SWIG_TypeName(const swig_type_info *); SWIGIMPORT(swig_type_info *) SWIG_TypeQuery(const char *); +SWIGIMPORT(swig_type_info *) SWIG_FindType(int(*)(swig_type_info *,void *),void *); SWIGIMPORT(void) SWIG_TypeClientData(swig_type_info *, void *); SWIGIMPORT(char *) SWIG_PackData(char *, void *, int); SWIGIMPORT(char *) SWIG_UnpackData(char *, void *, int); @@ -287,6 +288,27 @@ if (strcmp(name, iter->types[i]->name) == 0) return iter->types[i]; if (strcmp(name, iter->types[i]->str) == 0) + return iter->types[i]; + } + iter = iter->next; + } while (iter != swig_module_list); + + return 0; +} + +SWIGRUNTIME(swig_type_info *) +SWIG_FindType(int(*test)(swig_type_info *,void *),void *info) { + swig_module_info *iter; + int i; + + if (!swig_module_list) + return 0; + + iter = swig_module_list; + + do { + for (i = 0; i < iter->size; ++i) { + if (test(iter->types[i], info)) return iter->types[i]; } iter = iter->next; Index: Lib/perl5/perlrun.swg =================================================================== RCS file: /usr/local/cvs/Imports/SWIG-1.3.21/Lib/perl5/perlrun.swg,v retrieving revision 1.2 diff -u -u -r1.2 perlrun.swg --- Lib/perl5/perlrun.swg 19 May 2004 19:12:33 -0000 1.2 +++ Lib/perl5/perlrun.swg 25 May 2004 00:15:06 -0000 @@ -126,6 +126,8 @@ SWIG_Perl_ConvertPtr(pPerl, obj, pp, type, flags) # define SWIG_NewPointerObj(p, type, flags) \ SWIG_Perl_NewPointerObj(pPerl, p, type, flags) +# define SWIG_LangTypeQuery(type) \ + SWIG_Perl_LangTypeQuery(pPerl, type) # define SWIG_MakePackedObj(sv, p, s, type) \ SWIG_Perl_MakePackedObj(pPerl, sv, p, s, type) # define SWIG_ConvertPacked(obj, p, s, type, flags) \ @@ -136,6 +138,8 @@ SWIG_Perl_ConvertPtr(obj, pp, type, flags) # define SWIG_NewPointerObj(p, type, flags) \ SWIG_Perl_NewPointerObj(p, type, flags) +# define SWIG_LangTypeQuery(type) \ + SWIG_Perl_LangTypeQuery(type) # define SWIG_MakePackedObj(sv, p, s, type) \ SWIG_Perl_MakePackedObj(sv, p, s, type ) # define SWIG_ConvertPacked(obj, p, s, type, flags) \ @@ -175,6 +179,7 @@ SWIGIMPORT(int) SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *, void **, swig_type_info *, int flags); SWIGIMPORT(void) SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *, void *, swig_type_info *, int flags); SWIGIMPORT(SV *) SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *, swig_type_info *, int flags); +SWIGIMPORT(swig_type_info *) SWIG_Perl_LangTypeQuery(SWIG_MAYBE_PERL_OBJECT const char *) SWIGIMPORT(void) SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *, void *, int, swig_type_info *); SWIGIMPORT(int) SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *, void *, int, swig_type_info *, int flags); SWIGIMPORT(swig_type_info *) SWIG_Perl_TypeCheckRV(SWIG_MAYBE_PERL_OBJECT SV *rv, swig_type_info *ty); @@ -184,7 +189,7 @@ SWIGRUNTIME(swig_cast_info *) SWIG_Perl_TypeCheckRV(SWIG_MAYBE_PERL_OBJECT SV *rv, swig_type_info *ty) { - SWIG_TypeCheck_Template(sv_derived_from(rv, (char *) iter->type->name), ty); + SWIG_TypeCheck_Template(iter->type->clientdata && sv_derived_from(rv, (char *) iter->type->clientdata), ty); } /* Function for getting a pointer value */ @@ -257,7 +262,9 @@ SV *obj=newSV(0); HV *hash=newHV(); HV *stash; - sv_setref_pv(obj, (char *) t->name, ptr); + const char* pkg_name = (const char*)t->clientdata; + if (pkg_name == NULL) pkg_name = t->name; + sv_setref_pv(obj, pkg_name, ptr); stash=SvSTASH(SvRV(obj)); if (flags & SWIG_OWNER) { HV *hv; @@ -285,6 +292,19 @@ SWIG_MakePtr(result, ptr, t, flags); return result; } + +static int perl_type_matches(swig_type_info* info, void* dat) +{ + if (info->clientdata == NULL) return 0; + return strcmp((const char*)info->clientdata, (const char*)dat) == 0; +} + +SWIGRUNTIME(swig_type_info *) +SWIG_Perl_LangTypeQuery(SWIG_MAYBE_PERL_OBJECT const char *type) +{ + return SWIG_FindType(perl_type_matches, (void*) type); +} + SWIGRUNTIME(void) SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) { # You can make the package from CVS by something like: # tar -cvzf swig-1.3.11cvs.tar.gz SWIG-1.3.11cvs && rpm -tb swig-1.3.11cvs.tar.gz # swig.spec. Generated from swig.spec.in by configure. %define ver 1.3.21 %define rel 1rx %define prefix /usr %define home_page http://swig.sourceforge.net/ %define docprefix %{prefix}/share ###################################################################### # Usually, nothing needs to be changed below here between releases ###################################################################### Summary: Simplified Wrapper and Interface Generator Name: swig Version: %{ver} Release: %{rel} URL: %{home_page} Source0: %{name}-%{version}.tar.gz Patch0: SWIG-1.3.21-common-types.diff Patch1: SWIG-1.3.21-warnings.diff Patch2: SWIG-1.3.21-debug.diff Patch3: SWIG-1.3.21-qual.diff Patch4: SWIG-1.3.21-perlshadow.diff License: BSD Group: Development/Tools BuildRoot: %{_tmppath}/%{name}-root %description SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is primarily used with common scripting languages such as Perl, Python, Tcl/Tk, and Ruby, however the list of supported languages also includes non-scripting languages such as Java, OCAML and C#. Also several interpreted and compiled Scheme implementations (Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. %package runtime Summary: Runtime libraries required for dynamically loading swig-generated modules Group: Development/Libraries %description runtime The swig-runtime package contains shared libraries used to share type information between swig-generated modules loaded into the same application. Dynamically loading swig-generated modules should use the swig-runtime libs. %prep %setup -q -n SWIG-%{version} %patch0 -p0 %patch1 -p0 %patch2 -p0 %patch3 -p0 %patch4 -p0 %build # so we can build package from cvs source too [ ! -r configure ] && ./autogen.sh %configure make make runtime %install rm -rf ${RPM_BUILD_ROOT} # Why is exec_prefix not used in BIN_DIR in Makefile? %makeinstall prefix=${RPM_BUILD_ROOT}%prefix BIN_DIR=${RPM_BUILD_ROOT}%{_exec_prefix}/bin SWIG_LIB=${RPM_BUILD_ROOT}%prefix/lib/swig1.3 M4_INSTALL_DIR=${RPM_BUILD_ROOT}%prefix/share/aclocal install-runtime DIR=${RPM_BUILD_ROOT} find $DIR -type f | sed -e "s#^${RPM_BUILD_ROOT}##g" > %{name}.files %clean rm -rf ${RPM_BUILD_ROOT} %files # -f %{name}.files /usr/bin/* /usr/lib/swig* #%doc /usr/share/doc/swig* #/usr/share/doc/swig* /usr/share/aclocal/swig.m4 %defattr(-,root,root) %files runtime /usr/lib/lib* %changelog * Wed May 19 2004 <sfink@xxxxxxxxxx> 1.3.21-1rx - Added John Lenz's type propagation patch - Added warning suppressant patch - Fixed make install line (needs SWIG_LIB and M4_INSTALL_DIR directives) - Added 'install-runtime' target to make install line * Wed Jul 24 2002 Sam Liddicott <sam@xxxxxxxxxxxxx> - Added runtime package of runtime libs * Mon Sep 10 2001 Tony Seward <anthony.seward@xxxxxxxx> - Merge Red Hat's and Dustin Mitchell's .spec files. - Install all of the examples in the documantation directory. - Auto create the list of installed files. |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: Typedefs of template instantiations not recognized properly?: 00141, Steve Fink |
|---|---|
| Next by Date: | Re: how to prevent objects from being garbage collected.: 00141, William S Fulton |
| Previous by Thread: | renaming the .so in C->pythoni: 00141, Martin F Krafft |
| Next by Thread: | Re: [PATCH] assortment of problems: 00141, John Lenz |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |