cppgo
Call C++ from Go with no cgo at build time: generate a Go package from the headers, and let cppgo build the C++ shim that carries the rest.
cppgo gives a Go program an ordinary Go package that calls a C++ library. It writes the binding for you: the Go code that calls a library written in another language. You give it the library’s header — the C++ file a program includes to see its classes and functions — and the compilation configuration for that header, the directories your C++ compiler searches for included files and the language standard it compiles with. It writes a Go package that calls the library; this page calls it the generated package.
Your C++ sources, your build and your library are not modified, and the
generated package needs no cgo at build time and no import "C". cgo is
Go’s built-in way to call C: it needs a C compiler at build time and a special
import "C" block, which lets Go compile C code written beside it. cppgo loads
the compiled library at run time through a small Go library — the runtime —
that does not depend on cgo.
The input is the C++ header — here, the class the example binds, in
examples/mathx/include/mathx/vector.hpp:
#include <cstddef>
namespace mathx {
class Vector {
public:
Vector(double x, double y);
Vector(const Vector &other);
~Vector();
double x() const { return x_; }
double y() const;
double norm() const;
double dot(const double *ys, std::size_t n) const;
double at(std::size_t index) const;
void validate() const;
void scale(double k) noexcept;
static int dims();
private:
double x_;
double y_;
};
} // namespace mathx
Build the generator and run the example’s generation step:
$ make build
$ make -C examples/mathx gen
The example builds its own copy of the generator; from inside examples/mathx,
the generation command is:
$ build/cppgo gen -header include/mathx/vector.hpp -package mathx \
-library build/libmathx.so -out .
The result is an ordinary Go package. These are the declarations that class
became, copied from
examples/mathx/zz_cppgo.gen.go:
func NewVector(x float64, y float64) (*Vector, error)
func (v *Vector) Norm() (float64, error)
func (v *Vector) Scale(k float64)
func (v *Vector) Close() error
And you call it:
v, err := mathx.NewVector(3, 4)
if err != nil {
log.Fatal(err)
}
defer v.Close()
norm, err := v.Norm() // norm() can fail, so the Go call returns an error
if err != nil {
log.Fatal(err)
}
fmt.Println(norm) // 5
v.Scale(2) // scale() cannot fail, so there is no error to check
Start here
If you have never called C++ from Go before, read Bind your first C++ class. It takes one small C++ class from a header to a passing Go test, and explains each step.
The sections on the left follow the four kinds of documentation: a tutorial to learn, how-to guides for a task, reference for the exact signature, and explanation for how it works and why it is built this way.
Maturity
The generator, the runtime and the examples are implemented and tested. Three example modules bind a slice of a real library each — OpenCV, ArrayFire and Eigen — and each ships the tests that assert its values against the installed library.
Two things are designed and not shipped yet, and every page marks them where they appear: the full set of C++ failure conventions, and the remaining C++ construct support.
A slice covers the declarations the generator carries today, not the whole
library. cv::Mat, af::array and Eigen’s matrix types are not bound, so the
image, array and matrix work is not available through those modules, and
Limits names the refusal behind each.
Tutorials
Learning-oriented lessons that take you from nothing to a working binding.
- Bind your first C++ class
- Build a complete Go + C++ project
How-to guides
Task-oriented recipes for a specific problem you already have.
- Generate a binding for your own library
- Bind a C++ template library
- Ship a program that uses a binding
Reference
Information-oriented descriptions of the CLI, the generated API and the runtime.
- Command line
- Generated API
- Runtime
Explanation
Understanding-oriented discussion of why cppgo is built this way.
- Why cppgo exists
- The Go runtime and a native call
- Architecture