From: Eric B. <er...@go...> - 2001-05-27 09:30:07
|
Andreas Leitner wrote: > > ad 7) > External C dependencies make life really really hard... I have my > examples all setup very general. Due to the factory class they check > what back end parsers are compiled in and you can choose your favoriteat > runtime via a command line argument. This brings in some trouble at > build time though: I want to provide a simple way for the user to choose > at build time what backends he wants to have compiled in. This is > important because not everybody wants to go through the hassel and > install expat on his system. Also a possible compile_to_jvm is not > possible with expat dependencies in the build configuration. Now how can > I do that? With Makefiles of course, but they do not work on Windows ): > > Do you have any idea on how I can solve that issue? I thought that having expat/no_expat would solve the problem. One has just to choose one or the other in the Ace file at build-time. Did I miss something? BTW, I was surprised by your directory structure: impl/expat/expat/ep_event_parser_factory.e impl/expat/expat/... impl/expat/no_expat/ep_event_parser_factory.e I thought you would have done something like that: impl/expat/factory/ep_event_parser_factory.e impl/expat/... impl/no_expat/factory/ep_event_parser_factory.e I'm not saying that one is better than the other, but it seems more natural to me to choose whether I want to compile with expat or not at the impl level. Then you could have a loadpath.se, ise.ace, etc. in the directories: impl/expat impl/no_expat and include one or the other in your application loadpath or Ace file depending on whether you want to include expat or not. > ad 8) > In order to get actual data from expat I need to convert all kinds of C > strings (fixed length, zero terminated, ...) into Eiffel Strings (or > UCSTRINGs) C_STRING_HELPER is what I built to do that, but it is > compiler dependent of course. I think this is a good candidate for GOBO > itself (outside of the proper eXML clusters) - maybe with a few > modifications. Yes, it is clear that many libraries currently have their own string handling clusters, and one of the advantage of merging everything into Gobo is that we will be able to do some refactoring with all these classes, and possibly share them between libraries. You were suggesting putting these classes into the 'utility' library. Wouldn't all these string handling classes deserve a library on their own? Something like $GOBO/library/string? Then we could have: library/string/c_string /formatter /input /output /... The cluster c_string would be where to put your class since it is dependent on C (even though they don't have external routines) and applications compiled on .Net or JVM would not include this cluster. In the version of C_STRING_HELPER_NP for ISE Eiffel you wrote: make_pointer_from_string (s: STRING): POINTER is -- returns the pointer to the data of a specific string -- does this work with a moving gc?? make_pointer_from_string_buffer (data: SPECIAL [CHARACTER]): POINTER is -- returns the pointer to the data of a specific string -- does this work with a moving gc?? the answer is no: it is not safe when using a moving GC and you might get weird behaviors. The only safe way to pass pointers to Eiffel objects to C code is to use directly the $ construct in the arguments of the external routines. So I would suggest that you put all your external routines in a class *_EXTERNALS along with routines without POINTERs as arguments or results, and that you put this class in clusters spec/[ise|se|ve|hact] (you can possibly use 'gepp'). For example if you have an external C routine such as: char *foo (char *str) {} I would suggest that you have the following routines in your *_EXTERNALS class: feature -- Something here foo (str: STRING): STRING is -- ... require str_not_void: str /= Void local c_str: ANY do !! Result.make (0) c_str := str.to_c Result.from_c (c_foo ($c_str)) ensure foo_not_void: Result /= Void end feature {NONE} -- Externals c_foo (str: POINTER): POINTER is -- ... require str_not_null: str /= default_pointer external "C" alias "...." ensure c_foo_not_null: Result /= default_pointer end and provide different implementations for the different Eiffel compilers. This is in my opinion the only safe way with respect to moving GC to implement calls to C functions with pointers to Eiffel objects. It may look cumbersome at first, but it is actually cleaner because the public interface of this class does not involve POINTER, only pure Eiffel types. So if one day expat is ported to .Net or JVM you will have less work to do since the only class aware of the C language will be this class. Furthermore having this class *_EXTERNAL duplicated over the spec/[ise|se|ve|hact] clusters (once again yo can use 'gepp' to make its implementation and maintenance easier) has the other advantage of allowing you to use the different external C syntax enhancements provided by the different Eiffel compilers. We all know that they are not portable and we are stuck with the: external "C" syntax in order to have something portable, but since we already have the spec/[ise|se|ve|hact] clusters we can now take advantage of non-portable syntax. BTW, the routines above are functions, not procedures. So I suggest to name them `new_...' instead of `make_...'. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |