RAII Helpers

RAII helpers for managing lifetime of AngelScript objects.

Script Engine

inline script_engine asbind20::make_script_engine(asDWORD version = ANGELSCRIPT_VERSION)

Create an AngelScript engine.

class script_engine

Script engine manager.

Public Types

using handle_type = asIScriptEngine*

Public Functions

inline script_engine() noexcept
script_engine(const script_engine&) = delete
inline script_engine(script_engine&&) noexcept
inline explicit script_engine(handle_type engine) noexcept
script_engine &operator=(const script_engine&) = delete
inline script_engine &operator=(script_engine &&other) noexcept
inline ~script_engine()
inline handle_type get() const noexcept
inline operator handle_type() const noexcept
inline handle_type operator->() const noexcept
inline handle_type release() noexcept
inline void reset(handle_type engine = nullptr) noexcept

Script Context

inline auto asbind20::current_context() -> asIScriptContext*

Get current script context from a function called by script.

Returns:

A pointer to the currently executing context, or null if no context is executing

class request_context

RAII helper for requesting script context from the engine.

Public Types

using handle_type = asIScriptContext*

Public Functions

request_context() = delete
request_context(const request_context&) = delete
request_context &operator=(const request_context&) = delete
explicit request_context(std::nullptr_t) = delete
inline explicit request_context(asIScriptEngine *engine)
inline ~request_context()
inline handle_type get() const noexcept
inline auto get_engine() const noexcept -> asIScriptEngine*
inline operator handle_type() const noexcept
inline handle_type operator->() const noexcept
class reuse_active_context

RAII helper for reusing active script context.

It will fallback to request context from the engine.

Public Types

using handle_type = asIScriptContext*

Public Functions

reuse_active_context() = delete
reuse_active_context(const reuse_active_context&) = delete
reuse_active_context &operator=(const reuse_active_context&) = delete
explicit reuse_active_context(std::nullptr_t) = delete
inline explicit reuse_active_context(asIScriptEngine *engine, bool propagate_error = true)
inline ~reuse_active_context()
inline handle_type get() const noexcept
inline auto get_engine() const noexcept -> asIScriptEngine*
inline operator handle_type() const noexcept
inline handle_type operator->() const noexcept
inline bool is_nested() const noexcept

Returns true if current context is reused.

inline bool will_propagate_error() const noexcept

Script Object

class script_object

Smart pointer for script object.

Public Types

using handle_type = asIScriptObject*

Public Functions

script_object() noexcept = default
inline script_object(script_object &&other) noexcept
script_object(const script_object&) = delete
inline explicit script_object(handle_type obj)
inline ~script_object()
inline handle_type get() const noexcept
inline explicit operator handle_type() const noexcept
inline explicit operator bool() const noexcept
inline handle_type operator->() const noexcept
inline handle_type release() noexcept

Release without decreasing reference count.

Warning

USE WITH CAUTION!

Returns:

Previously stored object

inline void reset(std::nullptr_t = nullptr) noexcept

Reset object the null pointer.

inline void reset(handle_type obj)

Reset object.

Parameters:

obj – New object to store

Script Type Information

class script_typeinfo

RAII helper for asITypeInfo*.

Public Types

using handle_type = asITypeInfo*

Public Functions

script_typeinfo() noexcept = default
inline explicit script_typeinfo(std::in_place_t, handle_type ti) noexcept

Assign a type info object. It won’t increase the reference count!

See also

script_typeinfo(inplace_addref_t, handle_type)

Note

Generally, the AngelScript APIs for getting type info won’t increase reference count, such as being the hidden first argument of template class constructor/factory.

Warning

DON’T use this constructor unless you know what you are doing!

inline script_typeinfo(handle_type ti) noexcept

Assign a type info object, and increase reference count.

inline script_typeinfo(const script_typeinfo &other) noexcept
inline script_typeinfo(script_typeinfo &&other) noexcept
inline ~script_typeinfo()
inline script_typeinfo &operator=(const script_typeinfo &other) noexcept
inline script_typeinfo &operator=(script_typeinfo &&other) noexcept
inline handle_type get() const noexcept
inline handle_type operator->() const noexcept
inline operator handle_type() const noexcept
inline explicit operator bool() const noexcept
inline handle_type release() noexcept
inline void reset(std::nullptr_t = nullptr) noexcept
inline void reset(handle_type ti)
inline void reset(std::in_place_t, handle_type ti)
inline int type_id() const
inline int subtype_id(asUINT idx = 0) const
inline auto subtype(asUINT idx = 0) const -> asITypeInfo*

Lockable Shared Bool

class lockable_shared_bool

Helper for asILockableSharedBool*

This class can be helpful for implementing weak reference support.

Public Types

using handle_type = asILockableSharedBool*

Public Functions

lockable_shared_bool() noexcept = default
inline explicit lockable_shared_bool(handle_type bool_)
inline lockable_shared_bool(std::in_place_t, handle_type bool_) noexcept
inline lockable_shared_bool(const lockable_shared_bool &other)
inline lockable_shared_bool(lockable_shared_bool &&other) noexcept
inline ~lockable_shared_bool()
bool operator==(const lockable_shared_bool &other) const = default
inline void reset(std::nullptr_t = nullptr) noexcept
inline void reset(handle_type bool_) noexcept
inline void connect_object(void *obj, asITypeInfo *ti)

Connect to the weak reference flag of object.

Note

If it failed to connect, this helper will be reset to nullptr.

Parameters:
  • obj – Object to connect

  • ti – Type information

inline void reset(std::in_place_t, handle_type bool_) noexcept

See also

connect_object

Warning

If you get the lockable shared bool by GetWeakRefFlagOfScriptObject(), you should not use this function! Because it won’t increase the reference count.

inline lockable_shared_bool &operator=(const lockable_shared_bool &other)
inline lockable_shared_bool &operator=(lockable_shared_bool &&other)
inline void lock() const

Lock the flag.

inline void unlock() const noexcept

Unlock the flag.

inline bool get_flag() const
inline void set_flag(bool value = true)
inline handle_type get() const noexcept
inline handle_type operator->() const noexcept
inline operator handle_type() const noexcept
inline explicit operator bool() const noexcept
inline void swap(lockable_shared_bool &other) noexcept
inline lockable_shared_bool asbind20::make_lockable_shared_bool()

Create a lockable shared bool for implementing weak reference.

Note

Lock the exclusive lock in multithreading enviornment

IO Helpers

group Byte code manipulation

Functions

inline int save_byte_code(std::ostream &os, asIScriptModule *m, bool strip_debug_info = false)

Save byte code to std::ostream

Parameters:
  • os – Output stream

  • m – Script module to save

  • strip_debug_info – Strip debug information

Returns:

Result of asIScriptModule::SaveByteCode

template<typename OutputIteratorValueType = std::byte>
int save_byte_code(std::output_iterator<OutputIteratorValueType> auto out, asIScriptModule *m, bool strip_debug_info = false)

Save byte code to an output iterator.

Template Parameters:

OutputIteratorValueType – Value type of output iterator. It can be any integral type whose size equals to std::byte.

Parameters:
  • out – Output iterator

  • m – Script module

  • strip_debug_info – Strip debug information

Returns:

Result of asIScriptModule::SaveByteCode

inline io::load_byte_code_result load_byte_code(std::istream &is, asIScriptModule *m)

Load byte code from std::istream

Parameters:
  • is – Input stream

  • m – Script module

Returns:

Loading result

inline io::load_byte_code_result load_byte_code(const void *mem, std::size_t size, asIScriptModule *m)

Load byte code from memory buffer.

Parameters:
  • mem – Memory buffer

  • size – Buffer size

  • m – Script module

Returns:

Loading result

inline io::load_byte_code_result load_byte_code(std::span<const std::byte> mem, asIScriptModule *m)
struct load_byte_code_result

Result of loading byte code.

Public Functions

inline explicit operator bool() const noexcept

Will return true if r indicates the byte code was successfully loaded.

Public Members

int r

Loading result.

bool debug_info_stripped

Loading Script Sections

inline int asbind20::io::load_string(asIScriptModule *m, const char *section_name, std::string_view code, int line_offset = 0)

Load a string as script section.

Returns:

AngelScript error code

inline int asbind20::io::load_file(asIScriptModule *m, const std::filesystem::path &filename, std::ios_base::openmode mode = std::ios_base::in)

Load a file as script section.

Returns:

AngelScript error code

Miscellaneous Utilities

inline std::string asbind20::to_string(asEContextState state)

Convert context state enum to string.

Parameters:

state – Context state

Returns:

String representation of the state. If the state value is invalid, the result will be "asEContextState({state})", e.g. "asEContextState(-1)".

inline std::string asbind20::to_string(asERetCodes ret)

Convert return code to string.

Parameters:

ret – Return code

Returns:

String representation of the return code. If the value is invalid, the result will be "asERetCodes({ret})", e.g. "asERetCodes(1)".

template<detail::concat_accepted... Args>
constexpr std::string asbind20::string_concat(Args&&... args)

Concatenate strings.

Parameters:

args – String-like inputs

Returns:

std::string Result

Example:

using asbind20::string_concat;

// Concatenate any mix of string types
const char* method = "my_method";
std::string decl = string_concat("void f(", method, ')');
assert(decl == "void f(my_method)");

// Accepts std::string_view, cstring_ref, and characters
std::string s = string_concat("hello", ' ', std::string_view("world"));
assert(s == "hello world");
template<typename Fn, typename ...Args>
decltype(auto) asbind20::util::with_cstr(Fn &&fn, Args&&... args)

This function will convert string and string_view in parameters to null-terminated const char* for APIs receiving C-style string.

This function will make a copy of string view if it is not null-terminated.

with_cstr calls a callback with each argument converted to a null-terminated C string, handling any string-like type including std::string, std::string_view, cstring_ref, and util::fixed_string:

using asbind20::util::with_cstr;
using namespace std::string_view_literals;

std::string result = with_cstr(
    [](const char* a, const char* b, const char* c) {
        return std::string(a) + ' ' + b + ' ' + c;
    },
    "hello",
    "world"sv.substr(0, 3),  // "wor"
    asbind20::cstring_ref("!")
);
assert(result == "hello wor !");
template<std::size_t Size>
class fixed_string

Public Types

using value_type = char
using size_type = std::size_t

Public Functions

constexpr fixed_string(const fixed_string&) noexcept = default
template<std::convertible_to<char>... Chars>
inline explicit constexpr fixed_string(Chars... chs)
inline constexpr fixed_string(const char (&str)[Size + 1])
constexpr bool operator==(const fixed_string&) const noexcept = default
template<std::size_t N>
inline constexpr bool operator==(const fixed_string<N>&) const noexcept
inline constexpr const value_type *data() const noexcept
inline constexpr const value_type *c_str() const noexcept
inline constexpr operator cstring_ref() const noexcept
inline constexpr std::string_view view() const noexcept
inline constexpr operator std::string_view() const noexcept

Public Members

char internal_data[Size + 1] = {}

INTERNAL DATA. DO NOT USE!

This member is exposed for satisfying the NTTP requirements of C++.

Note

It includes \0 at the end.

Public Static Functions

static inline constexpr size_type size() noexcept
static inline constexpr bool empty() noexcept
template<typename T1, typename T2>
class compressed_pair

Compressed pair for saving storage space.

This class will use the empty base optimization (EBO) to reduce the size of compressed pair.

Template Parameters:
  • T1 – First member type

  • T2 – Second member type

Public Types

using first_type = T1
using second_type = T2
template<std::size_t Idx>
using element_type = std::conditional_t<Idx == 0, T1, T2>

Public Functions

compressed_pair() = default
compressed_pair(const compressed_pair&) = default
compressed_pair(compressed_pair&&) noexcept(std::is_nothrow_move_constructible_v<T1> && std::is_nothrow_move_constructible_v<T2>) = default
template<typename Tuple1, typename Tuple2>
inline compressed_pair(std::piecewise_construct_t, Tuple1 &&tuple1, Tuple2 &&tuple2)
inline compressed_pair(const T1 &t1, const T2 &t2)
inline compressed_pair(T1 &&t1, T2 &&t2) noexcept(std::is_nothrow_move_constructible_v<T1> && std::is_nothrow_move_constructible_v<T2>)
inline void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v<T1> && std::is_nothrow_swappable_v<T2>)

Friends

template<std::size_t Idx>
inline friend element_type<Idx> &get(compressed_pair &cp) noexcept
template<std::size_t Idx>
inline friend const element_type<Idx> &get(const compressed_pair &cp) noexcept
template<std::size_t Idx>
inline friend element_type<Idx> &&get(compressed_pair &&cp) noexcept
template<std::size_t Idx>
inline friend const element_type<Idx> &&get(const compressed_pair &&cp) noexcept

Example:

using asbind20::util::compressed_pair;

compressed_pair<int, int> p{0, 1};
assert(p.first() == 0);
assert(p.second() == 1);

p.first() = 2;
p.second() = 3;

// Structured binding support
auto& [a, b] = p;
assert(a == 2);
assert(b == 3);

// Swap
compressed_pair<int, int> q{4, 5};
p.swap(q);
assert(p.first() == 4 && p.second() == 5);

Atomic Reference Counting

atomic_counter wraps AngelScript’s asAtomicInc / asAtomicDec for thread-safe reference counting. It is designed for implementing the addref / release / get_refcount behaviours of a garbage-collected ref_class.

Constructing an atomic_counter initializes the counter to 1. Prefix ++ and -- call asAtomicInc and asAtomicDec respectively, returning the new value. The dec_and_try_destroy method decrements and, if the counter reaches 0, invokes a destroyer callback — typically delete on the enclosing object.

Example: implementing reference counting for a garbage-collected script object:

#include <asbind20/asbind.hpp>

class my_gc_object
{
public:
    void addref()
    {
        set_gc_flag(false);
        ++m_counter;
    }

    void release()
    {
        m_counter.dec_and_try_destroy(
            [](my_gc_object* self) { delete self; },
            this
        );
    }

    int get_refcount() const
    {
        return m_counter;
    }

    void set_gc_flag()  { m_flag = true; }
    bool get_gc_flag() const { return m_flag; }

    void enum_refs(asIScriptEngine*)  { /* enumerate references */ }
    void release_refs(asIScriptEngine*)  { /* release references */ }

private:
    asbind20::atomic_counter m_counter;
    bool m_flag = false;
};

// Register as a GC reference type
auto* engine = /* ... */;
asbind20::ref_class<my_gc_object>(engine, "my_gc_object", asOBJ_GC)
    .addref(fp<&my_gc_object::addref>)
    .release(fp<&my_gc_object::release>)
    .get_refcount(fp<&my_gc_object::get_refcount>)
    .set_gc_flag(fp<&my_gc_object::set_gc_flag>)
    .get_gc_flag(fp<&my_gc_object::get_gc_flag>)
    .release_refs(fp<&my_gc_object::release_refs>)
    .enum_refs(fp<&my_gc_object::enum_refs>)
    .default_factory(use_policy<policies::notify_gc>);

See the threading documentation for the full API reference.

Range Views

asbind20 provides range views for iterating over AngelScript entities — type members, behaviours, enum values, and even tokenized script source. When <ranges> is available (__cpp_lib_ranges), these views integrate with standard range adaptors and algorithms.

All views expose begin()/end(), size(), and empty(). Most iterators are random-access.

Type information views

These views wrap an asITypeInfo* and enumerate its contents:

#include <asbind20/ranges.hpp>

const asITypeInfo* ti = /* ... */;

// Iterate all methods (optionally exclude virtual methods)
for(auto* func : asbind20::views::all_methods(ti)) {
    std::cout << func->GetName() << '\n';
}

// Iterate all behaviours (constructors, destructors, opAssign, etc.)
for(auto [beh, func] : asbind20::views::all_behaviours(ti)) {
    std::cout << "behaviour " << beh << ": " << func->GetName() << '\n';
}

// Iterate all factories
for(auto* func : asbind20::views::all_factories(ti)) {
    std::cout << func->GetName() << '\n';
}

// Iterate all enum values
for(auto [name, value] : asbind20::views::all_enum_values(ti)) {
    std::cout << name << " = " << value << '\n';
}

The all_enum_values factory defaults to int as the underlying type. Use views::all_enum_values_of<std::uint64_t>(ti) for enums with a custom underlying type.

class all_methods_view : public asbind20::ranges::detail::view_interface<all_methods_view>

Public Types

using size_type = typename iterator::size_type

Public Functions

all_methods_view() = delete
all_methods_view(const all_methods_view&) noexcept = default
inline explicit all_methods_view(const asITypeInfo *ti, bool get_virtual = true) noexcept
inline size_type size() const
inline bool empty() const
inline iterator begin() const noexcept
inline iterator end() const noexcept
inline auto get_type_info() const noexcept -> const asITypeInfo*
class iterator : public asbind20::ranges::detail::indexed_iterator_interface<iterator>

Public Types

using value_type = asIScriptFunction*
using size_type = typename my_base::size_type

Public Functions

iterator() noexcept = default
iterator(const iterator&) noexcept = default
iterator &operator=(const iterator&) noexcept = default
inline bool operator==(const iterator &rhs) const noexcept
inline std::strong_ordering operator<=>(const iterator &rhs) const noexcept
inline explicit operator bool() const noexcept

Public Members

size_type index = 0
class all_behaviours_view : public asbind20::ranges::detail::view_interface<all_behaviours_view>

Public Types

using size_type = typename iterator::size_type

Public Functions

all_behaviours_view() = delete
all_behaviours_view(const all_behaviours_view&) noexcept = default
inline explicit all_behaviours_view(const asITypeInfo *ti) noexcept
inline size_type size() const
inline bool empty() const
inline iterator begin() const noexcept
inline iterator end() const noexcept
inline auto get_type_info() const noexcept -> const asITypeInfo*
class iterator : public asbind20::ranges::detail::indexed_iterator_interface<iterator>

Public Types

using value_type = std::pair<asEBehaviours, asIScriptFunction*>
using size_type = typename my_base::size_type

Public Functions

iterator() noexcept = default
iterator(const iterator&) noexcept = default
iterator &operator=(const iterator&) noexcept = default
inline bool operator==(const iterator &rhs) const noexcept
inline std::strong_ordering operator<=>(const iterator &rhs) const noexcept
inline explicit operator bool() const noexcept

Public Members

size_type index = 0
class all_factories_view : public asbind20::ranges::detail::view_interface<all_factories_view>

Public Types

using size_type = typename iterator::size_type

Public Functions

all_factories_view() = delete
all_factories_view(const all_factories_view&) noexcept = default
inline explicit all_factories_view(const asITypeInfo *ti) noexcept
inline size_type size() const
inline bool empty() const
inline iterator begin() const noexcept
inline iterator end() const noexcept
inline auto get_type_info() const noexcept -> const asITypeInfo*
class iterator : public asbind20::ranges::detail::indexed_iterator_interface<iterator>

Public Types

using value_type = asIScriptFunction*
using size_type = typename my_base::size_type

Public Functions

iterator() noexcept = default
iterator(const iterator&) noexcept = default
iterator &operator=(const iterator&) noexcept = default
inline bool operator==(const iterator &rhs) const noexcept
inline std::strong_ordering operator<=>(const iterator &rhs) const noexcept
inline explicit operator bool() const noexcept

Public Members

size_type index = 0
template<std::integral UnderlyingType = int>
class all_enum_values_view : public asbind20::ranges::detail::view_interface<all_enum_values_view<int>>

Public Types

using underlying_type = UnderlyingType
using size_type = typename iterator::size_type

Public Functions

all_enum_values_view() = delete
all_enum_values_view(const all_enum_values_view&) noexcept = default
inline explicit all_enum_values_view(const asITypeInfo *ti) noexcept
inline size_type size() const
inline bool empty() const
inline iterator begin() const noexcept
inline iterator end() const noexcept
inline auto get_type_info() const noexcept -> const asITypeInfo*
class iterator : public asbind20::ranges::detail::indexed_iterator_interface<iterator>

Public Types

using size_type = asUINT
using value_type = std::pair<cstring_ref, UnderlyingType>

Public Functions

iterator() noexcept = default
iterator(const iterator&) noexcept = default
iterator &operator=(const iterator&) noexcept = default
inline bool operator==(const iterator &rhs) const noexcept
inline std::strong_ordering operator<=>(const iterator &rhs) const noexcept
inline explicit operator bool() const noexcept

Public Members

size_type index = 0

Tokenize view

tokenize_view tokenizes a string of AngelScript source code lazily, yielding (asETokenClass, std::string_view) pairs:

#include <asbind20/ranges.hpp>

std::string_view code = "int foo = 42;";
for(auto [tc, sv] : asbind20::ranges::tokenize_view(engine, code)) {
    if(tc == asTC_IDENTIFIER)
        std::cout << "identifier: " << sv << '\n';
}

The view is an input range — it does not support random access or multi-pass iteration.

class tokenize_view : public asbind20::ranges::detail::view_interface<tokenize_view>

Public Functions

tokenize_view() = delete
tokenize_view(const tokenize_view&) = default
inline tokenize_view(const asIScriptEngine *engine, std::string_view code) noexcept
inline bool empty() const noexcept
inline iterator begin() const noexcept
inline auto get_engine() const noexcept -> const asIScriptEngine*

Public Static Functions

static inline sentinel end() noexcept
class iterator

Public Types

using iterator_category = std::input_iterator_tag
using value_type = std::pair<asETokenClass, std::string_view>
using size_type = std::size_t
using difference_type = std::ptrdiff_t

Public Functions

iterator() = default
inline explicit operator bool() const noexcept
inline bool operator==(const iterator &rhs) const noexcept
inline iterator &operator++()
inline void operator++(int)
inline const value_type &operator*() const noexcept

Friends

inline friend bool operator==(const iterator &lhs, sentinel) noexcept
inline friend bool operator==(sentinel, const iterator &rhs) noexcept
class sentinel

Debugging

inline const char *asbind20::debugging::get_function_section_name(const asIScriptFunction *func)

Get script section name of function.

This helper can handle the different interfaces for getting the section name across AngelScript versions.

Parameters:

func – Script function. It cannot be nullptr.

GC Statistics

struct gc_statistics

GC statistics.

Public Types

using value_type = asUINT
using tuple_type = std::tuple<value_type, value_type, value_type, value_type, value_type>

Public Functions

constexpr bool operator==(const gc_statistics&) const noexcept = default
constexpr std::strong_ordering operator<=>(const gc_statistics&) const noexcept = default
inline explicit operator tuple_type() const noexcept

Public Members

value_type current_size
value_type total_destroyed
value_type total_detected
value_type new_objects
value_type total_new_destroyed

Friends

template<std::size_t I>
inline friend constexpr value_type get(const gc_statistics &stats) noexcept
inline gc_statistics asbind20::debugging::get_gc_statistics(const asIScriptEngine *engine)

Get the GC statistics.

Parameters:

engine – Script engine. It cannot be nullptr.

String Extraction

Tools for extracting string from script without knowing its underlying type.

class extract_string_result

Result of string extraction.

Public Types

using error_type = asERetCodes
using value_type = std::string

Public Functions

extract_string_result() = delete
inline extract_string_result(const extract_string_result &other)
inline extract_string_result(extract_string_result &&other) noexcept
inline explicit extract_string_result(std::string str)
inline bool has_value() const noexcept
inline error_type error() const noexcept
inline value_type &operator*() noexcept
inline const value_type &operator*() const noexcept
inline value_type &value()
inline const value_type &value() const
inline extract_string_result asbind20::debugging::extract_string(const asIStringFactory *factory, const void *str)

Extracts the contents from a script string without knowing the underlying type.

Parameters:
  • factory – The string factory

  • str – The pointer to script string

Throws:

std::runtime_error – Failed to get the string

Returns:

std::string Result string