Invoking Script Interfaces

Invoking a Script Function

This library can automatically convert arguments in C++ for invoking an AngelScript function.

template<typename R, typename ...Args>
script_invoke_result<R> asbind20::script_invoke(asIScriptContext *ctx, asIScriptFunction *func, Args&&... args)

Call a script function.

This example assumes the std::string is registered as script string type. You can change the std::string to your underlying string type.

AngelScript function:

string test(int a, int&out b)
{
    b = a + 1;
    return "test";
}

C++ code:

asIScriptEngine* engine = /* Get a script engine */;
asIScriptModule* m = /* Build the above script */;
asIScriptFunction* func = m->GetFunctionByName("test");
if(!func)
    /* Error handling */

// Manage script context using the RAII helper
asbind20::request_context ctx(engine);

int val = 0;
auto result = asbind20::script_invoke<std::string>(
    ctx, func, 1, std::ref(val) // The reference needs a wrapper
);

assert(result.value() == "test");
assert(val == 2);

Using a Script Class

The library provides tools for instantiating a script class.

inline script_object asbind20::instantiate_class(asIScriptContext *ctx, const asITypeInfo *class_info)

Instantiate a script class using its default factory function.

Note

This function requires the class to be default constructible

Parameters:
  • ctx – Script context

  • class_info – Script class type information

Returns:

Instantiated script object, or empty object if failed

The script_invoke also supports invoking a method, a.k.a., member function. You need to put the script object in front of the script function pointer in arguments. This is designed to simulate a method call obj.method().

The type of script object can be either (const) void* or a type that can be cast into (const) asIScriptObject*.

template<typename R, script_object_handle Object, typename ...Args>
script_invoke_result<R> asbind20::script_invoke(asIScriptContext *ctx, Object &&obj, asIScriptFunction *func, Args&&... args)

Call a method on script object.

The script class defined in AngelScript:

class my_class
{
    int m_val;

    void set_val(int new_val) { m_val = new_val; }
    int get_val() const { return m_val; }
    int& get_val_ref() { return m_val; }
};

C++ code:

asIScriptEngine* engine = /* Get a script engine */;
asIScriptModule* m = /* Build the above script */;
asITypeInfo* my_class_t = m->GetTypeInfoByName("my_class");

asbind20::request_context ctx(engine);

auto my_class = asbind20::instantiate_class(ctx, my_class_t);

asIScriptFunction* set_val = my_class_t->GetMethodByDecl("void set_val(int)");
asbind20::script_invoke<void>(ctx, my_class, set_val, 182375);

asIScriptFunction* get_val = my_class_t->GetMethodByDecl("int get_val() const");
auto val = asbind20::script_invoke<int>(ctx, my_class, get_val);

assert(val.value() == 182375);

asIScriptFunction* get_val_ref = my_class_t->GetMethodByDecl("int& get_val_ref()");
auto val_ref = asbind20::script_invoke<int&>(ctx, my_class, get_val_ref);

assert(val_ref.value() == 182375);

*val_ref = 182376;

val = asbind20::script_invoke<int>(ctx, my_class, get_val);
assert(val.value() == 182376);

Script Function Objects

script_function and script_method wrap an asIScriptFunction* with ownership semantics, tracking the module reference count to keep the function valid even after the module is discarded. script_function_ref and script_method_ref are non-owning counterparts.

#include <asbind20/asbind.hpp>

auto engine = asbind20::make_script_engine();
auto* m = engine->GetModule("test", AS_NAMESPACE_QUALIFIER asGM_ALWAYS_CREATE);
m->AddScriptSection("test", "int test() { return 42; }");
m->Build();

// Owning wrapper — keeps the module alive
asbind20::script_function<int()> f(m->GetFunctionByName("test"));

m->Discard(); // module is discarded, but f still holds a reference

asbind20::request_context ctx(engine);
auto result = f(ctx);
assert(result.value() == 42);

// Non-owning lightweight reference
asbind20::script_function_ref<int()> rf = f;
assert(rf.target() == f.target());

// Convert ref back to owning
asbind20::script_function<int()> another = rf;
assert(another.target() == rf.target());

// Reset releases ownership
f.reset();
assert(!f);
assert(f.target() == nullptr);

script_method works the same way for member functions. Define a script class and wrap its methods:

auto* m2 = engine->GetModule("test2", AS_NAMESPACE_QUALIFIER asGM_ALWAYS_CREATE);
m2->AddScriptSection("test2",
    "class foo { int get_val() const { return 42; } };");
m2->Build();

auto* ti = m2->GetTypeInfoByName("foo");
auto foo_t = asbind20::script_typeinfo(ti);

asbind20::request_context ctx(engine);
auto foo = asbind20::instantiate_class(ctx, foo_t);

asbind20::script_method<int()> get_val(ti->GetMethodByName("get_val"));
auto val = get_val(ctx, foo);
assert(val.value() == 42);

// Non-owning ref
asbind20::script_method_ref<int()> rf = get_val;
auto val2 = rf(ctx, foo);
assert(val2.value() == 42);

Reference of Invocation Tools

template<typename R>
auto asbind20::get_context_result(asIScriptContext *ctx)

Get the result of context.

Template Parameters:

R – Return type. It can be safely ignored by void if you only want the error code

Parameters:

ctx – Script context. Cannot be nullptr.

Returns:

Result of the execution

The result types of script invocation consist of the primary template, specialization for references, and specialization for void.

template<typename T>
class script_invoke_result : public asbind20::script_invoke_result_base

Script invocation result.

Template Parameters:

T – Result type

Unchecked Accessors

Note

Please check the status of object before directly accessing the value!

inline return_type operator*() const
inline pointer_type operator->() const

Note

This function is only available if return type is reference or convertible to pointer

Checked Accessors

Throws an exception when the object does not contain a returned value

inline return_type value() const
template<typename U = std::remove_cv_t<T>>
inline value_type value_or(U &&default_val) const

Public Types

using value_type = T
using return_type = decltype(get_script_return<T>(std::declval<asIScriptContext*>()))
using pointer_type = typename detail::invoke_result_traits<return_type>::pointer_type

Public Functions

script_invoke_result(const script_invoke_result&) noexcept = default
script_invoke_result &operator=(const script_invoke_result &other) noexcept = default
~script_invoke_result() = default
inline std::optional<T> to_optional() const
inline explicit operator std::optional<T>() const
inline void swap(script_invoke_result &other) noexcept

The library also provides specializations for reference types (script_invoke_result<T&>) and void (script_invoke_result<void>).