-
Notifications
You must be signed in to change notification settings - Fork 113
Design decisions
The cgogen project consists of 3 parts: translator, generator and parser in order of importance. The first part was the translator that is responsible for name conversions from stuff_like_this_id()
into StuffLikeThisID()
, for type conversions from unsigned char *
to []byte
, from MyClass **
into **MyClass
or even []*MyClass
.
Translator does a lot of things, some parts of its engine are done right (name substitution, rule patterns, hints/tips for type conversions), other ones are done poorly because things turned out to be different in practice when I finished the first prototype and moved to experiments, however the quality is decent so I won't bother to rewrite that part.
Generator is mostly fine, however I don't like how pointer and references are handled, a better model from translator would fix that, but that's not so critical. The generator is based on fmt.Sprintf
mechanism and that helped a lot to avoid code bloat. Also it's very flexible, for an example, when Go 1.6 announced pointer rules, the required changes were including switching all allocations to C.malloc
calls, have a reference count object, implementing pointer borrowing and automatic frees with Finalizers, do nested allocations while unpacking slices like [][]string
and so on. I added all this to generator in a couple of days without a single hack. Thanks to the dynamic helpers mechanism, see gen_bindings.go
if curious.
Parser is actually a wrapper for cznic/cc C99 compiler frontend, by coincidence it has been under active development at the same time as I started this project (summer 2015), it was in alpha state and was unstable as hell. So I freezed the version that was stable enough and wrote the translator models based on the capabilities of CC at that moment. There was a lot stuff to guess. Then Jan has completed his CC project and I switched to the upstream master, at cost of having rewriting half of the translator logic, that's the true reason why its models are in so miserable state now. Parser being configured partly from the configuration manifest and partly from predefined options in predefined.go
.
All three modules are doing their best-outcome guesswork to handle the common cases in the most common ways, however when some configuration is needed, cgogen consults the configuration manifest for the project that usually has tree sections corresponding to the modules: GENERATOR
, PARSER
and TRANSLATOR
sorted in order of contents size.
The main executable provides the glue for all of three modules, it does config parsing, runs external utils like in-house pkg-config lightweight clone to discover more headers, manages the output buffers, formats the code using imports.Process
after generation is done and so on.
$ cgogen -h
╔═╗╔═╗╔═╗┌─┐┌─┐┌┐┌
║ ║ ╦║ ║│ ┬├┤ │││
╚═╝╚═╝╚═╝└─┘└─┘┘└┘
Usage: cgogen package1.yml [package2.yml] ...
See http://cgogen.com for examples and documentation.
Options:
-ccdefs
Try to steal built-in defines from a hosted C-compile, CC env variable must be set.
-debug
Enable some debug info.
-fancy
Enable fancy output in the term. (default true)
-nocgo
Do not include a cgo-specific header in resulting files.
-out dir
Specify a dir for the output.