Skip to content

Special Topics

Nested C++ code

The Birch language permits raw C++ code to be nested. Nesting C++ code requires some understanding of how the Birch compiler translates Birch code to C++ code, and this translation is still in flux.

The primary motivation for nested C++ is to wrap Birch language interfaces around existing C++ language libraries. The Birch standard library, for example, uses this feature to integrate parts of the C++ Standard Template Library and Eigen linear algebra library. The use of nested C++ code for other purposes is discouraged, and it is recommended that its use is kept to a minimum, with any lengthy or complex nested C++ code separated into dedicated header and source files.

When building a package, the Birch compiler creates one .hpp file per package, and one .cpp file per source.

To include raw C++ code in the .hpp file, use the following, typically at the root scope of a .bi file:

hpp{{
// C++ code here
}}

This is useful for #include directives, or for declaring C++ types and functions.

To include raw C++ code in the .cpp file, use the following, typically in the body of a function in a .bi file:

cpp{{
// C++ code here
}}

This is useful for executing arbitrary C++ code. It is beyond the scope of this document to detail all the ways in which such code may interface with C++ code generated by the Birch compiler. The following rules cover common use cases, however:

  • Variables declared in Birch code may be used as-named. Functions may be used by prefacing their name with the namespace bi::, and types with the namespace bi::type.
  • When using a member variable, or calling a member function or fiber, explicitly preface it with self-> to ensure correct copy-on-write handling of the current object. Never omit self->, and never use this->.
  • When using a local variable with a fiber, explicitly preface it with local-> to ensure correct copy-on-write handling of the current fiber state.
  • Nesting C++ code within fibers requires special care. Variables declared in nested C++ code will not be preserved between yields. One option is to wrap these as member variables within a Birch object that will be preserved between yields.

For good examples of using nested C++ code to wrap C/C++ library functionality, see Birch.SQLite, Birch.Cairo, and parts of Birch.Standard. For an in-depth study, see the C++ code generated by the Birch compiler in the build/latest/bi subdirectory of your Birch project, and the LibBirch C++ Library that supports the C++ code generated by the Birch compiler from Birch sources.