diff --git a/Manual.md b/Manual.md index 915c1f31..626455b2 100644 --- a/Manual.md +++ b/Manual.md @@ -1,204 +1,315 @@ -C++ C# interop bridge tool Developer's Manual +Clang/.NET code generation tool User's Manual +1. Introduction +=============== -1. Overview +What does it do? +---------------- + +This tool allows you to generate .NET bindings that wrap C/C++ code allowing interoperability with managed languages. This can be useful if you have an existing native codebase and want to add scripting support, or want to consume an existing native library in your managed code. + +Why reinvent the wheel? +----------------------- + +There are not many automated binding tools around, the only real alternative is SWIG. So how is it different from SWIG? + + * No need to generate a C layer to interop with C++. + * Based on an actual C++ parser (Clang) so very accurate. + * Understands C++ at the ABI (application binary interface) level + * Easily extensible semantics via user passes + * Strongly-typed customization APIs + * Can be used as a library + +2. Supported C/C++ language features +==================================== + +In this section we will go through how the generator deals with each C / C++ feature. + +C/C++ Types ----------- -This tool allows you to generate bindings that wrap C/C++ code allowing -interoperation in another language. This can be useful if you have an -existing native codebase and want to add scripting support, or want to -consume an existing native library in your managed code. +### Fundamental types -It differs from most existing C++ binding tools like SWIG in that it -does not generate a C layer to interop with C++, it actually understands -enough of the C++ ABI (application binary interface) to get the job done -without generating extra native code. +These are mapped to .NET types as follows: +1. Integral types -2. Architecture ---------------- + char -> System::Byte + bool -> System::Boolean + short -> System::Int16 + int, long -> System::Int32 + long long -> System::Int64 + + Signedness is also preserved in the conversions. -The tool is architected in the following layers: +2. Floating-point types - 1. Parser + float -> System::Single + double -> System::Double -Since writing bindings by hand is tedious and error-prone, an automated -approach is preferred. To do this, we use the open-source Clang parser -that provides us with an AST (Abstract Syntax Tree) of the code, ready -to be consumed by the generator. +3. Other types -By using a real compiler for parsing the code, we get mature support for -C and C++ features, like a fully-compliant preprocessor and support for -attributes and pragma directives that can affect the behaviour of the -code (ex. custom packing / alignment options). + wchar_t -> System::Char + void -> System::Void - 2. Generator (language-specific) +### Derived types -After parsing is done, a language-specific layer is generated. -Since different target languages provide different features, some C++ -language features are mapped in different ways by different languages. +1. Arrays -Since scripting languages have their own way of expressing certain -patterns, like properties (instead of getters/setters pairs), or -delegates (instead of function pointers) there is support to process -the generated bindings, to rename symbols, create additional helper -methods, map parameters. +These are mapped to .NET CLR arrays. -Aditionally some of it can be provided directly in the native source -code, by annotating the declarations with custom attributes. - - 3. Runtime (language-specific) +2. Function Pointers / Pointers to Members -This implements the C++ implementation-specific behaviours that allow -the target language to communicate with the native code. It will usually -use an existing FFI that provides support for interacting with C code. +These are mapped to .NET CLR delegates. -It needs to know about the object layout, virtual tables, RTTI and -exception low level details, so it can interoperate with the C++ code. +3. Pointers +These are mapped to .NET CLR references unless: -3. C/C++ features -------------------- + void* -> System::IntPtr + const char* -> System::String -In this section we will go through each relevant C / C++ feature and -go over how it is usually implemented and discuss different binding -strategies. +4. References - * Comments - - \brief Doxygen-style C++ comments are currently translated to .NET - XML-style comments. - - * Defines - - Defines can be translated to proper enumerations in C#. This needs - to be a manual operation for now. Other type of defines like strings - are currently not supported. +References are mapped to .NET CLR references just like pointers. - * Enumerations - -C/C++ enums are translated to proper enumerations in C#. +### Typedefs + +We do not preserve type definitions since .NET and its main language C# do not have the concept of type aliases like C/C++. There is an exception in the case of a typedef'd function (pointer) declaration. In this case generate a .NET delegate with the name of the typedef. + +Enums +----- + +C/C++ enums are translated automatically to .NET enumerations. + +Special cases to be aware of: -Beware that in the case of anonymous enums inside classes or namespaces, -they need to hoisted to an outer enclosing namespace. In some cases manual -rules need to be written for a good mapping. +1. Anonymous enums - Flags / Bitfields +C and C++ enums (this does not apply to the new C++11 strongly typed enums) do not introduce their own scope. This means the enumerated values will leak into an outer context, like a class or a namespace. When this is detected, the generator tries to map to an outer enclosing context and generate a new name. + +2. Flags / Bitfields -Some enums represent bitfields. The generator will try to apply an heuristic -to native enums to check if they represent flags. Most of the time it will -get it right and correctly apply the [Flags] .NET attribute to the wrapper -enum. If it guesses wrong (not enough enum values to make a good guess) -then you will need to make a rule to correct it. - - * Types - - Built in - (Wide) Chars (Unicode?) - Signed / Unsigned Int (8, 16, 32, 64) - Float / Doubles (32, 64) - - Modifiers - Value - Pointers - [C++] References +Some enumerations represent bitfield patterns. The generator tries to check for this with some heuristics. If there are enough values in the enum to make a good guess, we apply the [Flags] .NET attribute to the wrapper enum. + +Functions +--------- + +Since global scope functions are not supported in C# (though they are available in the CLR) they are mapped as a static function in a class, to be consumable by any CLS-compliant language. + +By default all globals functions of a translation unit are mapped to a static class with the name of of the unit prefixed by the namespace. + +Special cases to be aware of: + +1. Variadic arguments (TODO) + + C/C++ variadic arguments need careful handling because they are not contrained to be of the same type. + + .NET provides two types of variadic arguments support: + + * C# params-style + + This is the preferred and idiomatic method but can only be used when we know the variadic arguments will all be of the same type. Since we have no way to derive this fact from the information in C/C++ function signatures, you will need set this explicitly. + + * Argslist + + This is a lesser known method for variadic arguments in .NET and was added by Microsoft for better C++ compatibility in the runtime. As you can guess, this does support different types per variable argument but is more verbose and less idiomatic to use. By default we use this to wrap variadic functions. - * Functions +2. Default arguments -Since global scope functions are not supported in C# (though they are -available in CIL) they must be mapped as a static function in a class, -to be consumed by C# code. + We do not try to wrap arguments default values yet. This is desired but needs more research since potentially all C++ constant expressions can be used as default arguments, though it would be pretty simple to add this for the common case of null constants. - * Bitfields +Classes / Structs +----------------- -Not supported yet. Needs some research to check how to map to C#. +Unlike .NET, in which there is an explicit differentiation of the allocation semantics of the type in the form of classes (reference types) and structs (value types), in C++ both classes and structs are identical and can be used in both heap (malloc/new) and automatic (stack) allocations. - * Unions - -Not supported yet. Needs some research to check how to map to C#. +By default, classes and structs are wrapped as .NET reference types. If your type is supposed to be a value type, then you can instruct the generator to issue a .NET value type. You should use value types if the types are cheap to construct and/or if you creating a lot of instances. + +### POD (Plain Old Data) + +TODO: If the native type is a POD type, that means we can safely convert it to a value type. This would make the generator do the right thing by default and is pretty easy to implement. + +### Constructors + +Constructors are mapped to .NET class constructors. + +Note: An extra constructor is generated that takes a native pointer to the class. This allows construction of managed instances from native instances. + +### Destructors + +TODO: Destructors need to be mapped to the Dispose() pattern of .NET. + +### Overloaded Operators + +Most of the regular C++ operators can be mapped to .NET operator overloads. + +TODO: In case we get unsupported C++ operators then we should emit a warning, and introduce a new automatically named method to represent the operator. The user should then explicitly give a name to the operator to get rid of the warning. + +### Conversion Operators + +TODO: Convert C++ conversion operators to .NET conversion operators. + +### Inheritance + +C++ supports different types of implementation inheritance: + +1. Single inheritance + +This is the simplest case - * Type Definitions +2. Multiple inheritance + + + +3. Virtual inheritance + +This is not supported for now. + +### Bitfields + +This feature is not supported yet. + +### Unions -Not supported yet. Needs some research to check how to map to C#. +This feature is not supported yet. + +Templates +--------- + +Template types are supported at the moment + +At the moment, template specializations are not exported yet. + +Preprocessor defines +-------------------- + +Since C preprocessor definitions can be used for very different purposes, we can only do so much when converting them to managed code. - * Classes / Structs + 1. Numeric defines -Classes are wrapped in a native .NET class. Support for classes is currently -untested and still experimental. - - POD - Constructors - Destructors - Overloaded Operators - Conversion Operators - Methods - Static Members - Pointers to members + These can be translated to proper .NET enumerations. - Inheritance: - - 1. No inheritance - 2. Single inheritance - 3. Multiple inheritance - 4. Virtual inheritance + 2. String defines + + These can be translated to .NET static constant definitions. + + 3. Generalized expressions + + This case is not supported and probably never will. -* Templates + 4. Function-like macros + + This case is not supported and probably never will. -Not supported yet. Needs some research to check how to map to C#. +Comments +-------- -4. Customization ------------------- +Doxygen-style C++ comments are translated to .NET XML-style comments. This feature is experimental and limited to what Doxygen directives the upstream Clang parser supports. -The generator is extensible and some support for specific C++ features -will appear in the next versions: +3. Customization +================ - * STL - * Smart Pointers +The generator provides various ways to customize the generation process. -5. Target Languages -------------------- +Type Maps +--------- -At the moment the project is C#-specific. +If all you need to do is customize what gets generated for a type, then you can use the type maps feature. This lets you hook into the process for a specific type pattern. -6. ABI Internals ----------------- +### Standard library support -Each ABI specifies the internal implementation-specific details of how -C++ code works at the machine level, involving things like: +The generator provides type maps for the most common C/C++ standard library types: - 1. Class Layout - 2. Symbol Naming - 3. Virtual tables - 4. Exceptions - 5. RTTI (Run-time Type Information) +* String -There are two major C++ ABIs currently in use: +* Containers - 1. Microsoft (VC++ / Clang) - 2. Itanium (GCC / Clang) - -Each implementation differs in a lot of low level details, so we have to -implement specific code for each one. +1. Vector + +2. Map + +3. Set + +Passes +------ + +If you need more control then you can write your own pass. Passes have full access to the parsed AST (Abstract Syntax Tree) so you can modify the entire structure and declaration data of the source code. This is very powerful and should allow you to pretty much do anything you want. + +The generator already provides many ready-to-use passes that can transform +the wrapped code to be more idiomatic: + +### Renaming passes -The target runtime needs to support calling native methods. -This is usually implemented with an FFI (foreign function interface) in -the target language VM (virtual machine). +Use these to rename your declarations automatically so they follow .NET conventions. When setting up renaming passes, you can declare what kind of declarations they apply to. There are two different kinds of rename passes: -In most cases MSVC lays out classes in the following order: +1. Case renaming pass -1. Pointer to virtual functions table (_vtable_ or _vftable_), added only -when the class has virtual methods and no suitable table from a base class -can be reused. +This is a very simple to use pass that changes the case of the name of the declarations it matches. -2. Base classes +2. Regex renaming pass -3. Class members +This pass allows you to do powerful regex-based pattern matching renaming of declaration names. +### Function to instance method -7. Similiar Tools and Inspiration ---------------------------------- +This pass introduces instance methods that call a C/C++ global function. This can be useful to map "object-oriented" design in C to .NET classes. If your function +takes an instance to a class type as the first argument, then you can use this +pass. -https://github.com/mono/cxxi -http://code.google.com/p/bridj/ -http://code.google.com/p/jnaerator/ -http://dyncall.org/ +### Function to static method pass + +This pass introduces static methods that call a C/C++ global function. This can be useful to gather related global functions inside the object it belongs to semantically. + +### Getter/setter to property pass + +This pass introduces a property that calls the native C/C++ getter and setter function. This can make the API much more idiomatic and easier to use under .NET languages. + +### Internal passes + +Some internal functionalities are also implemented as passes like checking for invalid declaration names or resolving incomplete declarations. Please check the developer manual for more information about these. + +4. Targets +========== + +The backend of the generator is abstracted and it can target different .NET binding technologies: + +1. C++/CLI + + + +2. C# (P/Invoke) + + + + +5. Command Line Reference +========================= + +When you launch the executable with no options, you are presented with the following options: + +``` +Usage: Generator.exe [options]+ headers +Generates .NET bindings from C/C++ header files. + +Options: + -D, --defines=VALUE + -I, --include=VALUE + --ns, --namespace=VALUE + + -o, --outdir=VALUE + --debug + --lib, --library=VALUE + -t, --template=VALUE + -a, --assembly=VALUE + -v, --verbose + -h, -?, --help +``` + + * -D: Defines preprocessor macros (equivalent to #define). + + * -I: Specifies additional include directories. + + * -o: Specifies the base output directory for generated files. + + * -a: Specifies the .NET assembly that should be used as a driver. \ No newline at end of file