Hi, from Allen's previous proposal and the discussion that followed I wrote down another proposal for a high level pyplusplus API: http://i31www.ira.uka.de/~baas/pypp/ I haven't implemented that stuff yet, so far it's just a proposal for the API. The main differences to Allen's version: - I have merged the DeclWrapper and MultiDeclWrapper. A declaration wrapper can always contain a collection of declarations. - Instead of being a method of a class "Module" I have put the "control functions" (parse() et al) into a module. These functions don't represent an interface to the extension module, but they serve as an interface to the pyplusplus "core". - All global settings have to be done beforehand via special functions. The actual steps that pyplusplus does can then also be done internally. The user only has to do them manually when he wants to intercept and manipulate the generated data (such as the declaration tree or code creator tree). The API is not really complete yet, but there's enough to comment on it. One thing that's missing and that I'd like to change is what I mentioned in another mail, namely the introduction of "handles" to the output files. I think this can just be done by partitioning the code creators tree into individual parts (one part per output file). As I set the global arguments (such as whether the output consists of only one or several files) at the beginning this should be straightforward to incorporate. - Matthias -
On 2/17/06, Matthias Baas <baas@ira.uka.de> wrote:
Hi,
from Allen's previous proposal and the discussion that followed I wrote down another proposal for a high level pyplusplus API:
You did an amazing job.
I haven't implemented that stuff yet, so far it's just a proposal for the API.
I did, almost. Preview will be available to the end of next week.
The main differences to Allen's version:
- I have merged the DeclWrapper and MultiDeclWrapper. A declaration wrapper can always contain a collection of declarations.
As for me this is not a good idea. I think you will not be able to read the code. c = m.Class( name="set" ) Try to answer next question: does this code work on some concrete class or on all classes? Do you understand that this is fragile code?
- Instead of being a method of a class "Module" I have put the "control functions" (parse() et al) into a module. These functions don't represent an interface to the extension module, but they serve as an interface to the pyplusplus "core". - All global settings have to be done beforehand via special functions.
Can you explain why you prefer to have some global state? For example how can you find out what files pygccxml parsed? In order to do this you should know global variable name - implementation details.
The actual steps that pyplusplus does can then also be done internally. The user only has to do them manually when he wants to intercept and manipulate the generated data (such as the declaration tree or code creator tree).
The API is not really complete yet, but there's enough to comment on it. One thing that's missing and that I'd like to change is what I mentioned in another mail, namely the introduction of "handles" to the output files. I think this can just be done by partitioning the code creators tree into individual parts (one part per output file). As I set the global arguments (such as whether the output consists of only one or several files) at the beginning this should be straightforward to incorporate.
I will look at it later, okay?
- Matthias -
-- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Roman Yakovenko wrote:
I haven't implemented that stuff yet, so far it's just a proposal for the API.
I did, almost. Preview will be available to the end of next week.
Oops, I have already implemented a "prototype" myself. I also did some updates on the documentation: http://i31www.ira.uka.de/~baas/pypp/ A zip containing the implementation of the API is available on the above page (direct link here: http://i31www.ira.uka.de/~baas/pypp/pyppapi_1.zip) Almost everything that is mentioned in the documentation is implemented, except for the addMethod() method (but there is now an alternative: cdef() which is equivalent to def() in Boost.Python). I converted my project to the above API which made the whole thing more maintainable. I have cranked up the number of wrapped classes in my project to 222 and best of all, meanwhile I can even *import* the module in Python. :) The registering order was still a problem, so I just disabled keyword generation on all constructors and since then, importing was no problem anymore.
The main differences to Allen's version:
- I have merged the DeclWrapper and MultiDeclWrapper. A declaration wrapper can always contain a collection of declarations.
As for me this is not a good idea. I think you will not be able to read the code. c = m.Class( name="set" )
Try to answer next question: does this code work on some concrete class or on all classes? Do you understand that this is fragile code?
Right, in the above example it could be that c references several classes (from several namespaces) called "set". I see your point and I felt somewhat uneasy about that myself at the beginning. That's why I introduced a new argument "assert_count" that checks the number of matched declarations and raises an exception if it differs from the expected number. In the current implementation, the above line could be written as: c = Class("set", assert_count=1) This will guarantee that c references exactly one class (by the way, another alternative would have been to use the 'fullname' filter right from the beginning: c = Class(fullname="::set")). Now that I've used the API on my own project it turned out that I didn't use the above assert_count feature in a single place as this hasn't been a problem anyway. All the classes in the SDK are unique, so it's safe to refer to them just by name. And in the case of methods I was actually using the feature to reference several methods at once quite often, so now I'd even say the feature is too powerful to be discarded! :) For example, as I said above I wanted to disable keyword generation on all constructors of all SDK classes (which start with the letter 'M'). I did that with just the following line: Class("/M.*/").Constructor().disableKeywordArgs() Another example is excluding all protected member functions. This can simply be accomplished with the following line: Method(accesstype=PROTECTED).ignore() This selects *all* protected methods among all classes and ignores them. Another advantage of leaving the assertion out is that during development and testing you can even leave out classes from parsing (because you want to test one particular class) without having to comment out all the decoration stuff (as the Class(), Method(), etc selections can also be empty). I'm aware however that this can also be a disadvantage as you won't notice any typos or similar mistakes. So I agree that an *optional* assertion mechanism like above or even an "auto assertion" feature can be useful. But it should definitely be possible to disable these assertions.
- Instead of being a method of a class "Module" I have put the "control functions" (parse() et al) into a module. These functions don't represent an interface to the extension module, but they serve as an interface to the pyplusplus "core". - All global settings have to be done beforehand via special functions.
Can you explain why you prefer to have some global state?
I introduced the "global" parameters so that the parameters for the individual steps (parse(), codeCreators(), writeFiles()) are known to pyplusplus (or rather the high level API) in advance. This means the steps can be done by pyplusplus internally and the user only has to do them manually when he wants to intercept and halt the pipeline at a particular stage. If parse() et al would take arguments, pyplusplus wouldn't be able to call those functions internally.
For example how can you find out what files pygccxml parsed? In order to do this you should know global variable name - implementation details.
Well, it's the user who has to pass the names (or patterns) to pyplusplus, so he should already know the headers. But you're right, when you pass a file pattern (such as "sdk/*.h") you won't know exactly which files got included. Currently, the header() function only returns the number of included files which could be changed to returning a list of included files. Meanwhile I also tested the caching feature. I noticed that the cache *always* is written to disk, even if it hasn't changed. Can this be changed so that it only gets written when there was a modification to the data in the cache? Currently, parsing my header files takes about three minutes without using a cache (222 header files). When using the cache, the parsing step still takes about 2 minutes (when the cache file is already available). I suppose a good deal of that 2 minutes is used for writing the file back to disk, right? The cache file itself has about 40MB. Is there any chance to split that into smaller chunks? Occasionally, for testing purposes I only generate bindings that contain a few selected classes. In this case, using the cache is less efficient than parsing the headers directly (as the cache file is so large and contains a lot of stuff that I don't need when only wrapping a small subset). Then I have another feature wish. I think it would be useful to introduce a "verbosity level" and have pyplusplus generate status messages. For example, I modified pygccxml so that it displays the header file it is currently parsing. I found it rather soothing to see the file names and know that pygccxml is still doing something useful instead of having to stare at a static console window for several minutes where nothing seems to happen. :) I added those two lines to the create_xml_file() function: print >>sys.stderr, "\015%s"%(60*" "), print >>sys.stderr, "\015%s..."%header, Actually, I would suggest to introduce callback functions that get called by pyplusplus and that can then do the actual output. This way, the user can customize the output (for example for doing the output in a graphical front end or writing a log file). - Matthias -
participants (2)
-
Matthias Baas -
Roman Yakovenko