https://github.com/thelartians/glue
⛓️ Bindings that stick. A simple and generic API for C++ to other language bindings supporting bidirectional communication, inheritance and automatic declarations.
https://github.com/thelartians/glue
automatic bindings cpp declarations glue inheritance language-bindings multi-language scripting-language typescript
Last synced: 2 months ago
JSON representation
⛓️ Bindings that stick. A simple and generic API for C++ to other language bindings supporting bidirectional communication, inheritance and automatic declarations.
- Host: GitHub
- URL: https://github.com/thelartians/glue
- Owner: TheLartians
- License: mit
- Created: 2018-06-25T14:16:14.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-12-12T21:10:22.000Z (almost 5 years ago)
- Last Synced: 2025-04-30T10:43:37.144Z (5 months ago)
- Topics: automatic, bindings, cpp, declarations, glue, inheritance, language-bindings, multi-language, scripting-language, typescript
- Language: C++
- Homepage:
- Size: 1.46 MB
- Stars: 57
- Watchers: 5
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: Readme.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/TheLartians/Glue/actions)
[](https://github.com/TheLartians/Glue/actions)
[](https://github.com/TheLartians/Glue/actions)
[](https://github.com/TheLartians/Glue/actions)
[](https://github.com/TheLartians/Glue/actions)
[](https://codecov.io/gh/TheLartians/Glue)# Glue
A common interface for C++ to other language bindings.
## Motivation
C++ is a great language for writing algorithms and high-performance code.
However, once it comes to building applications, servers or websites, simple things become complex and we settle for a scripting language to glue C++ components together.
The bindings usually need to be hand-crafted for every exposed type and language.
This project aims to create a generic language binding interface in pure standard C++, which allows two-way interactions, automatic declaration creation and relatively short compile times.## API
### Maps and values
Glue is based on the [Revisited framework](https://github.com/thelartians/Revisited) and provides convenient wrapper methods.
The most important types for creating the API and are `glue::Value` and `glue::MapValue`.```cpp
#include
#includevoid valueExample() {
// `glue::Value`s hold an `revisited::Any` type that can store any type of value
glue::Value value = "Hello glue!";// access the any type through the `->` or `*` operator
// `as()` returns an `std::optional` that is defined if the cast is possible
std::cout << *value->as() << std::endl;// `glue::MapValue` is a wrapper for a container that maps strings to values
// `glue::createAnyMap()` creates a map based on `std::unordered_set`
// Values also accept lambda functions
glue::MapValue map = glue::createAnyMap();
map["myNumber"] = 42;
map["myString"] = value;
map["myCallback"] = [](bool a, float b){ return a ? b : -b; };
map["myMap"] = glue::createAnyMap();// use helper functions to cast to maps or callbacks.
// the result will evaluate to `false` if no cast is possible.
if (auto f = map["myCallback"].asFunction()) {
// callbacks are stored as a `revisited::AnyFunction` and can accept both values or `Any` arguments
// (here `map["myNumber"]` is casted to an `Any` through the `*` operator)
// `get` returns casts the value to `T` or throws an exception if not possible
std::cout << f(false, *map["myNumber"]).get() << std::endl;
}// inner maps are also `glue::MapValue`s.
map["myMap"].asMap()["inner"] = "inner value";
}
```### Classes
Glue also has built-in support for maps representing classes and inheritance.
```cpp
#include
#include
#includestruct A {
std::string member;
};struct B: public A {
B(std::string value) : A{value} {}
int method(int v) { return int(member.size()) + v; }
};void classExample() {
auto map = glue::createAnyMap();// `glue::createClass` is a convience function for declaring maps for class APIs
// `addConstructor()` adds a function that constructs `A` given the argument types `Args...`
// `.addMember("name", &T::member)` adds a setter (`member`) and getter (`setMember`) function
map["A"] = glue::createClass()
.addConstructor<>()
.addMember("member", &A::member)
;// classes can be made inheritance aware
// `setExtends(map)` uses the argument map or callback to retrieve undefined keys
// `glue::WithBases()` adds implicit conversions to the listed base classes
// `addMethod("name", &T::method)` adds a method that calls a member function or lambda
map["B"] = glue::createClass(glue::WithBases())
.setExtends(map["A"])
.addConstructor()
.addMethod("method", &B::method)
.addMethod("lambda", [](const B &b, int x){ return b.member.size() + x; })
;// contexts collect map class data and can be used to test instance creation
glue::Context context;
context.addRootMap(map);// `glue::Instance` captures a value and behaves as a class instance
auto b = context.createInstance(map["B"][glue::keys::constructorKey]("arg"));// calls will be treated as member functions
std::cout << b["member"]().get() << std::endl;
b["setMember"]("new value");
std::cout << b["lambda"](10).get() << std::endl;
}
```### Declarations
Glue can automatically generate declarations for type-safe scripting using TypeScript or [TypeScriptToLua](https://typescripttolua.github.io).
```cpp
glue::DeclarationPrinter printer;
printer.init();
printer.print(std::cout, map, &context);
```In the example above, this would result in the following declarations.
```ts
/** @customConstructor A.__new */
declare class A {
constructor()
member(): string
setMember(arg1: string): void
}
/** @customConstructor B.__new */
declare class B extends A {
constructor(arg0: string)
lambda(arg1: number): number
method(arg1: number): number
}
```## Supported bindings
Here you can find current and planned bindings for Glue.
- [x] Lua: [LuaGlue](https://github.com/TheLartians/LuaGlue)
- [x] JavaScript (Wasm): [EmGlue](https://github.com/TheLartians/EmGlue)
- [ ] JavaScript (Duktape)
- [ ] Python
- [ ] Java
- [ ] Swift
- [ ] RustAs you can see, many bindings are still missing from the list.
If you've created Glue bindings for any language, feel free to open a PR to add them here.## Limitations
- No support for pointer or optional arguments in callbacks (yet)
- Class bindings aren't as sophisticated as other libraries bindings such as [sol2](https://github.com/ThePhD/sol2)
- There is a small overhead through the additional abstraction layer compared to native bindings## Usage
Glue can be easily added to your project using [CPM.cmake](https://github.com/TheLartians/CPM.cmake).
```cmake
CPMAddPackage(
NAME Glue
VERSION 1.0
GIT_REPOSITORY https://github.com/TheLartians/Glue.git
)target_link_libraries(myLibrary Glue)
```See [here](https://github.com/TheLartians/TypeScriptXX) for an example project using Glue to create TypeScript bindings for C++.