Advertisement

[Library Announcement] Binding Generator Library for AngelScript

Started by November 11, 2024 05:35 PM
5 comments, last by WitchLord 2 weeks, 5 days ago

I've made a binding generator for AngelScript at https://github.com/HenryAWE/asbind20.

The basic feature is almost complete. The library is preparing for its first release. I think it is worth to share this library here, as well as asking for suggestion & feedback.

Although the interface of AngelScript is very friendly to C++ comparing to most binding APIs from other script languages, it still needs many additional proxy functions (e.g. when binding a constructor). However, most of these proxies have similar logic, so they can be generated by some template tricks.

This library provides tools for calling script function. You won't need to manually choose asIScriptContext::SetArgXxx() / asIScriptContext::GetReturnXxx() with correct types. It also has RAII utilities for managing lifetime of asIScriptContext.

In general, my library aims to automate everything that can be generated by template meta-programing. You can check the README in repository for further information.

None

Nice! 🙂

I'll need to take a closer look at this later on, but I'll definitely add a link to it on the “Further resources” page.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

WitchLord said:

Nice! 🙂

I'll need to take a closer look at this later on, but I'll definitely add a link to it on the “Further resources” page.

Thanks.

I have a question when writing the binding generator. If the proxy function, such as a wrapper for constructor, is auto-generated, which native calling convention is preferred?

I noticed that the official add-on and documentation seems to prefer asCALL_CDECL_OBJLAST. In my past experience, many C++ libraries put the parameter equivalent to this at first when simulating a member function (i.e. method) using global function. The utilities from standard library such as std::invoke also treats the first argument as class object when needed. Is putting the object parameter at the last position have advantage in performance or portability?

None

There is no specific reason for using one or the other. Both work equally well. It is just a matter of preference.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

🎉The 1.0.0 version of library is done.

Primary features are:

  1. Conveniently bind C++ functions / classes to AngelScript, including auto-generated wrappers for constructors / factories / operators. These generated wrappers can be native or generic based on user's choice.
  2. Tools for interacting with script function / asIScriptGeneric without manually choosing correct function of a specific type.
  3. Generating generic wrapper for functions of any parameter count at compile-time, without using any macro.
  4. Dispatching function calls based on type ids, similar to std::visit & std::variant. This is for dealing with templated classes or variable argument (e.g. ?&in).
  5. RAII tools for managing locks and contexts.

The repository contains demonstrations located under ext/ directory. It shows how to bind common things like array, string, dictionary, and math functions using asbind20.

@WitchLord Besides, does using asCALL_THISCALL have advantage in performance compared to asCALL_CDECL_OBJFIRST/LAST with a wrapper?

My current implemented logic for binding generator is to try a member function at first, then fallback to wrapper function for finding function by ADL.

For example, when generating a opEquals from operator==, the binding generator will firstly try bool type::operator==(const type&) const. If this member function not exists, the binding generator will use a lambda to find other suitable operator==, because it can be declared as friend bool operator==(const type&, const type&):

[](const type& lhs, const type& rhs) -> bool
{
    return lhs == rhs;
}

However, the later one can handle the member function too. If using member function doesn't have advantages, maybe I can simplify compile-time logic of binding generator, that can probably increase compile speed.

None

HenryAWE said:
@WitchLord Besides, does using asCALL_THISCALL have advantage in performance compared to asCALL_CDECL_OBJFIRST/LAST with a wrapper?

There is no obvious advantage to generally say that one is better than the other. It can vary on a case by case due to logic for marshalling the values from the script stack to the native application cpu registers & stack. It may also differ based on the platform, so one setup can potentially be faster on Windows, but slower in Linux. But the difference should be small and unnoticeable unless you have a truly high frequent call (in which case it might be better to avoid using scripting at all, or go with JIT compilation).

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement