Giter Site home page Giter Site logo

thelartians / glue Goto Github PK

View Code? Open in Web Editor NEW
55.0 6.0 2.0 1.5 MB

⛓️ Bindings that stick. A simple and generic API for C++ to other language bindings supporting bidirectional communication, inheritance and automatic declarations.

License: MIT License

CMake 26.22% C++ 73.78%
cpp bindings automatic glue multi-language typescript declarations language-bindings scripting-language inheritance

glue's Introduction

Actions Status Actions Status Actions Status Actions Status Actions Status codecov

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 and provides convenient wrapper methods. The most important types for creating the API and are glue::Value and glue::MapValue.

#include <glue/value.h>
#include <iostream>

void 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<T>()` returns an `std::optional<T>` that is defined if the cast is possible
  std::cout << *value->as<std::string>() << 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<T>` returns casts the value to `T` or throws an exception if not possible
    std::cout << f(false, *map["myNumber"]).get<int>() << 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.

#include <glue/class.h>
#include <glue/context.h>
#include <iostream>

struct 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<T>` is a convience function for declaring maps for class APIs
  // `addConstructor<Args...>()` 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<A>()
    .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<A>()` 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<B>(glue::WithBases<A>())
    .setExtends(map["A"])
    .addConstructor<std::string>()
    .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::string>() << std::endl;
  b["setMember"]("new value");
  std::cout << b["lambda"](10).get<int>() << std::endl;
}

Declarations

Glue can automatically generate declarations for type-safe scripting using TypeScript or TypeScriptToLua.

glue::DeclarationPrinter printer;
printer.init();
printer.print(std::cout, map, &context);

In the example above, this would result in the following declarations.

/** @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.

  • Lua: LuaGlue
  • JavaScript (Wasm): EmGlue
  • JavaScript (Duktape)
  • Python
  • Java
  • Swift
  • Rust

As 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
  • 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.

CPMAddPackage(
  NAME Glue
  VERSION 1.0
  GIT_REPOSITORY https://github.com/TheLartians/Glue.git
)

target_link_libraries(myLibrary Glue)

See here for an example project using Glue to create TypeScript bindings for C++.

glue's People

Contributors

thelartians avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

glue's Issues

Duktape / V8 integration

The Glue bindings are designed to be language agnostic, which should allow easy creation of bindings to other languages. As Glue is currently only used in TypeScript projects bindings to embedded JavaScript interpreters like Duktape or V8 would be great.
Documentation is very sparse atm but if anyone feels up to the challenge I'd be happy to provide assistance.

Add more bindings

See the readme for the current wishlist of Glue bindings. So far only Lua and Wasm bindings have been implemented. Feel free to comment here if you are interested in contributing with bindings for any language.

Using smart pointer constructor

Thanks for a really useful library!

Is it possible to make addConstructor use smart pointers?

I.e., in emscripten I can do

EMSCRIPTEN_BINDINGS(better_smart_pointers) {
    class_<C>("C")
        .smart_ptr_constructor("C", &std::make_unique<C>)
        ;
}

My cpp library works with smart pointers all the time. Now I want to utilize it in Typescript via emglue.

Is that possible?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.