More AngelScript binding wrappers

Started by
27 comments, last by WitchLord 12 years, 1 month ago
As I apparently do fairly frequently, I was thinking about AngelScript binding again. One of the annoyances of using the current autowrapper add-on is that to create a generic wrapper you need two steps: to define the proxy function and then register it, and since the proxy has to be declared at namespace scope, this separates registration into two different places. By using function pointers as non-type template arguments to the proxy functions, I've come up with a way to simplify that. Basically any function you would normally register with asFUNCTION() and asCALL_CDECL you can register with WRAP_FN() instead of asFUNCTION(). Ex:

if (use_generic) {
r = engine->RegisterGlobalFunction("void print(string & in)", WRAP_FN(print), asCALL_GENERIC); assert(r >= 0);
} else {
r = engine->RegisterGlobalFunction("void print(string & in)", asFUNCTION(print), asCALL_CDECL); assert(r >= 0);
}

Similarly WRAP_MFN() can be used instead of asMETHOD() and asCALL_THISCALL, WRAP_OBJ_FIRST() instead of asCALL_CDECL_OBJFIRST and WRAP_OBJ_LAST() instead of asCALL_CDECL_OBJLAST. There are also PR versions of the macros for overloads. (The PR macros are actually more straightforward than the regular ones; the mechanism I originally wanted for the non-PR macros ended up crashing MSVC 2010.)

The one major limitation with this is the variable parameter type, e.g.: (?&in). Since AngelScript passes variable parameters to generic and non-generic functions in fundamentally different ways, I can't think of a reasonable mechanism to map one to the other.

While I was at it, I also worked on automatic wrappers for use with smart pointers as value types. This includes creating getters and setters as well as functions to automatically invoke member functions. They can be used to generate either generic or native functions.

An example file demonstrating both at work:

#include "angelscript.h"
#include "scriptstdstring.h"

#include "as_smart_ptr_wrapper.h"
#include "as_gen_wrapper.h"

#include <iostream>
#include <cassert>
#include <cstdio>

#include <memory>

// Types to export

struct Base {
virtual ~Base() {}

void moo(void) const { std::cout << "Moo." << std::endl; }
};

struct Derived : Base {
int x;
int y;

void moo(void) const { std::cout << "Moo!" << std::endl; }
void add(int value) { x += value; y += value; }

int & getter(void) { return x; }
};

typedef std::shared_ptr<Base> BasePtr;
typedef std::shared_ptr<Derived> DerivedPtr;

// Helper functions

template <typename T>
void construct(void * address) {
new (address) T;
}

template <typename T>
void destroy(T * object) {
object->~T();
}

template <typename T>
void copy_construct(void * address, T * other) {
new (address) T(*other);
}

template <typename T>
void assign(T * lhs, T* rhs) {
*lhs = *rhs;
}

void MessageCallback(const asSMessageInfo *msg, void *param)
{
const char *type = "ERR ";
if (msg->type == asMSGTYPE_WARNING) {
type = "WARN";
} else if (msg->type == asMSGTYPE_INFORMATION) {
type = "INFO";
}

printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
}

void __cdecl print(const std::string & str) {
std::cout << str;
}

template <typename T>
T foo(T);

int main(int, char **) {
asIScriptEngine * engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
RegisterStdString(engine);

bool use_generic = strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY");

int r;
if (use_generic) {
r = engine->RegisterGlobalFunction("void print(string & in)", WRAP_FN(print), asCALL_GENERIC); assert(r >= 0);
} else {
r = engine->RegisterGlobalFunction("void print(string & in)", asFUNCTION(print), asCALL_CDECL); assert(r >= 0);
}

// Base
r = engine->RegisterObjectType("Base", sizeof(BasePtr), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert(r >= 0);
if (use_generic) {
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_CONSTRUCT, "void f()", WRAP_OBJ_FIRST(construct<BasePtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_CONSTRUCT, "void f(const Base & in)", WRAP_OBJ_FIRST(copy_construct<BasePtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_DESTRUCT, "void f()", WRAP_OBJ_FIRST(destroy<BasePtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Base", "Base &opAssign(const Base &in)", WRAP_OBJ_FIRST(assign<BasePtr>), asCALL_GENERIC); assert(r >= 0);

r = engine->RegisterObjectMethod("Base", "void moo(void) const", GEN_CALLER(Base, moo), asCALL_GENERIC); assert(r >= 0);
} else {
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(construct<BasePtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_CONSTRUCT, "void f(const Base & in)", asFUNCTION(copy_construct<BasePtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(destroy<BasePtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Base", "Base &opAssign(const Base &in)", asFUNCTION(assign<BasePtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);

r = engine->RegisterObjectMethod("Base", "void moo(void) const", CALLER(Base, moo), asCALL_CDECL_OBJFIRST); assert(r >= 0);
}

// Derived
r = engine->RegisterObjectType("Derived", sizeof(DerivedPtr), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert(r >= 0);
if (use_generic) {
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_CONSTRUCT, "void f()", WRAP_OBJ_FIRST(construct<DerivedPtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_CONSTRUCT, "void f(const Derived & in)", WRAP_OBJ_FIRST(copy_construct<DerivedPtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_DESTRUCT, "void f()", WRAP_OBJ_FIRST(destroy<DerivedPtr>), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "Derived &opAssign(const Derived & in)", WRAP_OBJ_FIRST(assign<DerivedPtr>), asCALL_GENERIC); assert(r >= 0);

r = engine->RegisterObjectMethod("Derived", "const int & get_x() const", REF_GETTER_GEN(Derived, x), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void set_x(const int & in)", REF_SETTER_GEN(Derived, x), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "int get_y() const", GETTER_GEN(Derived, y), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void set_y(int)", SETTER_GEN(Derived, y), asCALL_GENERIC); assert(r >= 0);

r = engine->RegisterObjectMethod("Derived", "void moo(void) const", GEN_CALLER(Derived, moo), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void add(int)", GEN_CALLER(Derived, add), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "int & getter(void)", GEN_CALLER(Derived, getter), asCALL_GENERIC); assert(r >= 0);
} else {
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(construct<DerivedPtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_CONSTRUCT, "void f(const Derived & in)", asFUNCTION(copy_construct<DerivedPtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(destroy<DerivedPtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "Derived &opAssign(const Derived & in)", asFUNCTION(assign<DerivedPtr>), asCALL_CDECL_OBJFIRST); assert(r >= 0);

r = engine->RegisterObjectMethod("Derived", "const int & get_x() const", REF_GETTER(Derived, x), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void set_x(const int & in)", REF_SETTER(Derived, x), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "int get_y() const", GETTER(Derived, y), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void set_y(int)", SETTER(Derived, y), asCALL_CDECL_OBJFIRST); assert(r >= 0);

r = engine->RegisterObjectMethod("Derived", "void moo(void) const", CALLER(Derived, moo), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "void add(int)", CALLER(Derived, add), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectMethod("Derived", "int & getter(void)", CALLER(Derived, getter), asCALL_CDECL_OBJFIRST); assert(r >= 0);
}

// conversions
if (use_generic) {
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_VALUE_CAST, "Derived f() const", WRAP_OBJ_FIRST((std::dynamic_pointer_cast<Derived, Base>)), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_IMPLICIT_VALUE_CAST, "Base f() const", WRAP_OBJ_FIRST((std::static_pointer_cast<Base, Derived>)), asCALL_GENERIC); assert(r >= 0);
} else {
r = engine->RegisterObjectBehaviour("Base", asBEHAVE_VALUE_CAST, "Derived f() const", asFUNCTION((std::dynamic_pointer_cast<Derived, Base>)), asCALL_CDECL_OBJFIRST); assert(r >= 0);
r = engine->RegisterObjectBehaviour("Derived", asBEHAVE_IMPLICIT_VALUE_CAST, "Base f() const", asFUNCTION((std::static_pointer_cast<Base, Derived>)), asCALL_CDECL_OBJFIRST); assert(r >= 0);
}

const char script[] =
"void foo(const Base & in ptr) {\n"
" ptr.moo();\n"
" Derived d = Derived(ptr);\n"
" print(d.x + \"\\n\");\n"
" print(d.y + \"\\n\");\n"
" d.getter() = 3;\n"
" d.y = 4;\n"
" d.moo();\n"
" d.add(1);\n"
"}\n"
;

asIScriptModule * mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
r = mod->AddScriptSection("script", script, sizeof(script) - 1); assert(r >= 0);
r = mod->Build(); assert(r >= 0);

int func_id = mod->GetFunctionIdByDecl("void foo(const Base & in)");

Derived * d = new Derived;
d->x = 1;
d->y = 2;
BasePtr base(d);


asIScriptContext * ctx = engine->CreateContext();
ctx->Prepare(func_id);
ctx->SetArgObject(0, &base);
ctx->Execute();

ctx->Release();

engine->Release();

std::cout << d->x << std::endl;
std::cout << d->y << std::endl;
}

A header for the generic wrappers good for up to four arguments:

#ifndef AS_GEN_WRAPPER_H
#define AS_GEN_WRAPPER_H

#include "angelscript.h"
#include <new>

namespace gw {

template <typename T> class Proxy {
public:
T value;
Proxy(T value) : value(value) {}
static T cast(void * ptr) {
return reinterpret_cast<Proxy<T> *>(&ptr)->value;
}
private:
Proxy(const Proxy &);
Proxy & operator=(const Proxy &);
};

template <typename T> struct Wrapper {};
template <typename T> struct ObjFirst {};
template <typename T> struct ObjLast {};

template <>
struct Wrapper<void (*)(void)> {
template <void (*fp)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)());
}
};

template <typename R>
struct Wrapper<R (*)(void)> {
template <R (*fp)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)());
}
};

template <typename T>
struct Wrapper<void (T::*)(void)> {
template <void (T::*fp)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)());
}
};

template <typename T, typename R>
struct Wrapper<R (T::*)(void)> {
template <R (T::*fp)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)());
}
};

template <typename T>
struct Wrapper<void (T::*)(void) const> {
template <void (T::*fp)(void) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)());
}
};

template <typename T, typename R>
struct Wrapper<R (T::*)(void) const> {
template <R (T::*fp)(void) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)());
}
};

template <typename T>
struct ObjFirst<void (*)(T)> {
template <void (*fp)(T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R>
struct ObjFirst<R (*)(T)> {
template <R (*fp)(T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T>
struct ObjLast<void (*)(T)> {
template <void (*fp)(T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R>
struct ObjLast<R (*)(T)> {
template <R (*fp)(T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename A0>
struct Wrapper<void (*)(A0)> {
template <void (*fp)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename R, typename A0>
struct Wrapper<R (*)(A0)> {
template <R (*fp)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename A0>
struct Wrapper<void (T::*)(A0)> {
template <void (T::*fp)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename R, typename A0>
struct Wrapper<R (T::*)(A0)> {
template <R (T::*fp)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename A0>
struct Wrapper<void (T::*)(A0) const> {
template <void (T::*fp)(A0) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename R, typename A0>
struct Wrapper<R (T::*)(A0) const> {
template <R (T::*fp)(A0) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename A0>
struct ObjFirst<void (*)(T, A0)> {
template <void (*fp)(T, A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename R, typename A0>
struct ObjFirst<R (*)(T, A0)> {
template <R (*fp)(T, A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
};

template <typename T, typename A0>
struct ObjLast<void (*)(A0, T)> {
template <void (*fp)(A0, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R, typename A0>
struct ObjLast<R (*)(A0, T)> {
template <R (*fp)(A0, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename A0, typename A1>
struct Wrapper<void (*)(A0, A1)> {
template <void (*fp)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename R, typename A0, typename A1>
struct Wrapper<R (*)(A0, A1)> {
template <R (*fp)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename A0, typename A1>
struct Wrapper<void (T::*)(A0, A1)> {
template <void (T::*fp)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename R, typename A0, typename A1>
struct Wrapper<R (T::*)(A0, A1)> {
template <R (T::*fp)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename A0, typename A1>
struct Wrapper<void (T::*)(A0, A1) const> {
template <void (T::*fp)(A0, A1) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename R, typename A0, typename A1>
struct Wrapper<R (T::*)(A0, A1) const> {
template <R (T::*fp)(A0, A1) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename A0, typename A1>
struct ObjFirst<void (*)(T, A0, A1)> {
template <void (*fp)(T, A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename R, typename A0, typename A1>
struct ObjFirst<R (*)(T, A0, A1)> {
template <R (*fp)(T, A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
};

template <typename T, typename A0, typename A1>
struct ObjLast<void (*)(A0, A1, T)> {
template <void (*fp)(A0, A1, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R, typename A0, typename A1>
struct ObjLast<R (*)(A0, A1, T)> {
template <R (*fp)(A0, A1, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename A0, typename A1, typename A2>
struct Wrapper<void (*)(A0, A1, A2)> {
template <void (*fp)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (*)(A0, A1, A2)> {
template <R (*fp)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename A0, typename A1, typename A2>
struct Wrapper<void (T::*)(A0, A1, A2)> {
template <void (T::*fp)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (T::*)(A0, A1, A2)> {
template <R (T::*fp)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename A0, typename A1, typename A2>
struct Wrapper<void (T::*)(A0, A1, A2) const> {
template <void (T::*fp)(A0, A1, A2) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct Wrapper<R (T::*)(A0, A1, A2) const> {
template <R (T::*fp)(A0, A1, A2) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename A0, typename A1, typename A2>
struct ObjFirst<void (*)(T, A0, A1, A2)> {
template <void (*fp)(T, A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct ObjFirst<R (*)(T, A0, A1, A2)> {
template <R (*fp)(T, A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
};

template <typename T, typename A0, typename A1, typename A2>
struct ObjLast<void (*)(A0, A1, A2, T)> {
template <void (*fp)(A0, A1, A2, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct ObjLast<R (*)(A0, A1, A2, T)> {
template <R (*fp)(A0, A1, A2, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (*)(A0, A1, A2, A3)> {
template <void (*fp)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (*)(A0, A1, A2, A3)> {
template <R (*fp)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (T::*)(A0, A1, A2, A3)> {
template <void (T::*fp)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (T::*)(A0, A1, A2, A3)> {
template <R (T::*fp)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<void (T::*)(A0, A1, A2, A3) const> {
template <void (T::*fp)(A0, A1, A2, A3) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (T::*)(A0, A1, A2, A3) const> {
template <R (T::*fp)(A0, A1, A2, A3) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct ObjFirst<void (*)(T, A0, A1, A2, A3)> {
template <void (*fp)(T, A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct ObjFirst<R (*)(T, A0, A1, A2, A3)> {
template <R (*fp)(T, A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
Proxy<T>::cast(gen->GetObject()),
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct ObjLast<void (*)(A0, A1, A2, A3, T)> {
template <void (*fp)(A0, A1, A2, A3, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct ObjLast<R (*)(A0, A1, A2, A3, T)> {
template <R (*fp)(A0, A1, A2, A3, T)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
new (gen->GetAddressOfReturnLocation()) Proxy<R>((fp)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value,
Proxy<T>::cast(gen->GetObject())));
}
};

template <typename T>
struct Id {
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr f(void) { return asFUNCTION(&(Wrapper<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr of(void) { return asFUNCTION(&(ObjFirst<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr ol(void) { return asFUNCTION(&(ObjLast<T>::f<fn_ptr>)); }
};

template <typename T>
Id<T> id(T fn_ptr) { return Id<T>(); }

#define WRAP_FN(name) (::gw::id(name).f< name >())
#define WRAP_MFN(ClassType, name) (::gw::id(&ClassType::name).f< &ClassType::name >())
#define WRAP_OBJ_FIRST(name) (::gw::id(name).of< name >())
#define WRAP_OBJ_LAST(name) (::gw::id(name).ol< name >())

#define WRAP_FN_PR(name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (*)Parameters>::f< name >))
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::f< &ClassType::name >))
#define WRAP_OBJ_FIRST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjFirst<ReturnType (*)Parameters>::f< name >))
#define WRAP_OBJ_LAST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjLast<ReturnType (*)Parameters>::f< name >))

} // end namespace gw

#endif

A python script to regenerate the file in case four arguments aren't enough for you:

max_args = 4 # the maximum number of parameters to be processed

print """#ifndef AS_GEN_WRAPPER_H
#define AS_GEN_WRAPPER_H

#include "angelscript.h"
#include <new>

namespace gw {

template <typename T> class Proxy {
public:
T value;
Proxy(T value) : value(value) {}
static T cast(void * ptr) {
return reinterpret_cast<Proxy<T> *>(&ptr)->value;
}
private:
Proxy(const Proxy &);
Proxy & operator=(const Proxy &);
};

template <typename T> struct Wrapper {};
template <typename T> struct ObjFirst {};
template <typename T> struct ObjLast {};
"""

typename_list = "typename A0"
type_list = "A0"
arg_list = "\n static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value"
new_exp = "new (gen->GetAddressOfReturnLocation()) Proxy<R>"
obj_exp = "static_cast<T *>(gen->GetObject())->*"
obj_arg_exp = "\n Proxy<T>::cast(gen->GetObject())"

template = """template <{0}{1}>
struct {9}<{2} ({3}*)({7}){4}> {{
template <{2} ({3}*fp)({7}){4}>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{5}(({6}fp)({8}));
}}
}};
"""

print template.format("", "", "void", "", "", "", "", "void", "", "Wrapper")
print template.format("typename R", "", "R", "", "", new_exp, "", "void", "", "Wrapper")
print template.format("typename T", "", "void", "T::", "", "", obj_exp, "void", "", "Wrapper")
print template.format("typename T, typename R", "", "R", "T::", "", new_exp, obj_exp, "void", "", "Wrapper")
print template.format("typename T", "", "void", "T::", " const", "", obj_exp, "void", "", "Wrapper")
print template.format("typename T, typename R", "", "R", "T::", " const", new_exp, obj_exp, "void", "", "Wrapper")

print template.format("typename T", "", "void", "", "", "", "", "T", obj_arg_exp, "ObjFirst")
print template.format("typename T, typename R", "", "R", "", "", new_exp, "", "T", obj_arg_exp, "ObjFirst")
print template.format("typename T", "", "void", "", "", "", "", "T", obj_arg_exp, "ObjLast")
print template.format("typename T, typename R", "", "R", "", "", new_exp, "", "T", obj_arg_exp, "ObjLast")

for i in range(0, max_args):
print template.format("", typename_list, "void", "", "", "", "", type_list, arg_list, "Wrapper")
print template.format("typename R, ", typename_list, "R", "", "", new_exp, "", type_list, arg_list, "Wrapper")
print template.format("typename T, ", typename_list, "void", "T::", "", "", obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, typename R, ", typename_list, "R", "T::", "", new_exp, obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, ", typename_list, "void", "T::", " const", "", obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, typename R, ", typename_list, "R", "T::", " const", new_exp, obj_exp, type_list, arg_list, "Wrapper")

print template.format("typename T, ", typename_list, "void", "", "", "", "", "T, " + type_list, obj_arg_exp + "," + arg_list, "ObjFirst")
print template.format("typename T, typename R, ", typename_list, "R", "", "", new_exp, "", "T, " + type_list, obj_arg_exp + "," + arg_list, "ObjFirst")
print template.format("typename T, ", typename_list, "void", "", "", "", "", type_list + ", T", arg_list + "," + obj_arg_exp, "ObjLast")
print template.format("typename T, typename R, ", typename_list, "R", "", "", new_exp, "", type_list + ", T", arg_list + "," + obj_arg_exp, "ObjLast")

typename_list += ", typename A{0}".format(i + 1)
type_list += ", A{0}".format(i + 1)
arg_list += ",\n static_cast<Proxy <A{0}> *>(gen->GetAddressOfArg({0}))->value".format(i + 1)

print """template <typename T>
struct Id {
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr f(void) { return asFUNCTION(&(Wrapper<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr of(void) { return asFUNCTION(&(ObjFirst<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr ol(void) { return asFUNCTION(&(ObjLast<T>::f<fn_ptr>)); }
};

template <typename T>
Id<T> id(T fn_ptr) { return Id<T>(); }

#define WRAP_FN(name) (::gw::id(name).f< name >())
#define WRAP_MFN(ClassType, name) (::gw::id(&ClassType::name).f< &ClassType::name >())
#define WRAP_OBJ_FIRST(name) (::gw::id(name).of< name >())
#define WRAP_OBJ_LAST(name) (::gw::id(name).ol< name >())

#define WRAP_FN_PR(name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (*)Parameters>::f< name >))
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::f< &ClassType::name >))
#define WRAP_OBJ_FIRST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjFirst<ReturnType (*)Parameters>::f< name >))
#define WRAP_OBJ_LAST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjLast<ReturnType (*)Parameters>::f< name >))

} // end namespace gw

#endif"""

A smart pointer header also good for up to four arguments:

#ifndef AS_SMART_POINTER_WRAPPER
#define AS_SMART_POINTER_WRAPPER

#include <new>
#include "angelscript.h"
#include <memory>

namespace spw {

template <typename T> struct Default {
static T f(void) { return T(); }
};
template <typename T> struct Default<T &> {
static T & f(void) { return *static_cast<T *>(0); }
};

template <typename T> class Proxy {
public:
T value;
Proxy(T value) : value(value) {}
private:
Proxy(const Proxy &);
Proxy & operator=(const Proxy &);
};

template <typename T, typename U, U T::*member_ptr>
U getter(const std::shared_ptr<T> & ptr) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
return Default<U>::f();
}
return (ptr.get())->*member_ptr;
}

template <typename T, typename U, U T::*member_ptr>
const U & ref_getter(const std::shared_ptr<T> & ptr) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
return Default<U &>::f();
}
return (ptr.get())->*member_ptr;
}

template <typename T, typename U, U T::*member_ptr>
void getter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<U>((ptr.get())->*member_ptr);
}
}

template <typename T, typename U, U T::*member_ptr>
void ref_getter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<U &>((ptr.get())->*member_ptr);
}
}

template <typename T, typename U, U T::*member_ptr>
void setter(const std::shared_ptr<T> & ptr, U value) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
(ptr.get())->*member_ptr = value;
}
}

template <typename T, typename U, U T::*member_ptr>
void ref_setter(const std::shared_ptr<T> & ptr, const U & value) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
(ptr.get())->*member_ptr = value;
}
}

template <typename T, typename U, U T::*member_ptr>
void setter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
(ptr.get())->*member_ptr = static_cast<Proxy<U> *>(gen->GetAddressOfArg(0))->value;
}
}

template <typename T, typename U, U T::*member_ptr>
void ref_setter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
} else {
(ptr.get())->*member_ptr = static_cast<Proxy<U &> *>(gen->GetAddressOfArg(0))->value;
}
}

template <typename T> struct Caller {};
template <typename T> struct GenCaller {};

template <typename T, typename R>
struct Caller<R (T::*)(void)> {
template <R (T::*fn)(void)>
static R f(std::shared_ptr<T> & ptr) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)();
}
}
};

template <typename T, typename R>
struct Caller<R (T::*)(void) const> {
template <R (T::*fn)(void) const>
static R f(std::shared_ptr<T> & ptr) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)();
}
}
};

template <typename T>
struct GenCaller<void (T::*)(void)> {
template <void (T::*fn)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)();
}
}
};

template <typename T, typename R>
struct GenCaller<R (T::*)(void)> {
template <R (T::*fn)(void)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)());
}
}
};

template <typename T>
struct GenCaller<void (T::*)(void) const> {
template <void (T::*fn)(void) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)();
}
}
};

template <typename T, typename R>
struct GenCaller<R (T::*)(void) const> {
template <R (T::*fn)(void) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)());
}
}
};

template <typename T, typename R, typename A0>
struct Caller<R (T::*)(A0)> {
template <R (T::*fn)(A0)>
static R f(std::shared_ptr<T> & ptr, A0 a0) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0);
}
}
};

template <typename T, typename R, typename A0>
struct Caller<R (T::*)(A0) const> {
template <R (T::*fn)(A0) const>
static R f(std::shared_ptr<T> & ptr, A0 a0) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0);
}
}
};

template <typename T, typename A0>
struct GenCaller<void (T::*)(A0)> {
template <void (T::*fn)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value);
}
}
};

template <typename T, typename R, typename A0>
struct GenCaller<R (T::*)(A0)> {
template <R (T::*fn)(A0)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
}
};

template <typename T, typename A0>
struct GenCaller<void (T::*)(A0) const> {
template <void (T::*fn)(A0) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value);
}
}
};

template <typename T, typename R, typename A0>
struct GenCaller<R (T::*)(A0) const> {
template <R (T::*fn)(A0) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value));
}
}
};

template <typename T, typename R, typename A0, typename A1>
struct Caller<R (T::*)(A0, A1)> {
template <R (T::*fn)(A0, A1)>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1);
}
}
};

template <typename T, typename R, typename A0, typename A1>
struct Caller<R (T::*)(A0, A1) const> {
template <R (T::*fn)(A0, A1) const>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1);
}
}
};

template <typename T, typename A0, typename A1>
struct GenCaller<void (T::*)(A0, A1)> {
template <void (T::*fn)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1>
struct GenCaller<R (T::*)(A0, A1)> {
template <R (T::*fn)(A0, A1)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
}
};

template <typename T, typename A0, typename A1>
struct GenCaller<void (T::*)(A0, A1) const> {
template <void (T::*fn)(A0, A1) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1>
struct GenCaller<R (T::*)(A0, A1) const> {
template <R (T::*fn)(A0, A1) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value));
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct Caller<R (T::*)(A0, A1, A2)> {
template <R (T::*fn)(A0, A1, A2)>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1, A2 a2) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1, a2);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct Caller<R (T::*)(A0, A1, A2) const> {
template <R (T::*fn)(A0, A1, A2) const>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1, A2 a2) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1, a2);
}
}
};

template <typename T, typename A0, typename A1, typename A2>
struct GenCaller<void (T::*)(A0, A1, A2)> {
template <void (T::*fn)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct GenCaller<R (T::*)(A0, A1, A2)> {
template <R (T::*fn)(A0, A1, A2)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
}
};

template <typename T, typename A0, typename A1, typename A2>
struct GenCaller<void (T::*)(A0, A1, A2) const> {
template <void (T::*fn)(A0, A1, A2) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2>
struct GenCaller<R (T::*)(A0, A1, A2) const> {
template <R (T::*fn)(A0, A1, A2) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value));
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Caller<R (T::*)(A0, A1, A2, A3)> {
template <R (T::*fn)(A0, A1, A2, A3)>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1, A2 a2, A3 a3) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1, a2, a3);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Caller<R (T::*)(A0, A1, A2, A3) const> {
template <R (T::*fn)(A0, A1, A2, A3) const>
static R f(std::shared_ptr<T> & ptr, A0 a0, A1 a1, A2 a2, A3 a3) {
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
} else {
return ((ptr.get())->*fn)(a0, a1, a2, a3);
}
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct GenCaller<void (T::*)(A0, A1, A2, A3)> {
template <void (T::*fn)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct GenCaller<R (T::*)(A0, A1, A2, A3)> {
template <R (T::*fn)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
}
};

template <typename T, typename A0, typename A1, typename A2, typename A3>
struct GenCaller<void (T::*)(A0, A1, A2, A3) const> {
template <void (T::*fn)(A0, A1, A2, A3) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value);
}
}
};

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct GenCaller<R (T::*)(A0, A1, A2, A3) const> {
template <R (T::*fn)(A0, A1, A2, A3) const>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
std::shared_ptr<T> & ptr = *static_cast<std::shared_ptr<T> *>(gen->GetObject());
if (!ptr) {
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
} else {
new (gen->GetAddressOfReturnLocation()) Proxy<R>(((ptr.get())->*fn)(
static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
}
};

template <typename T, typename U>
struct GetSet {
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr g(void) { return asFUNCTION(( &getter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rg(void) { return asFUNCTION((&ref_getter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr gg(void) { return asFUNCTION(( &getter_gen<T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rgg(void) { return asFUNCTION((&ref_getter_gen<T, U, member_ptr>)); }

template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr s(void) { return asFUNCTION((&setter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rs(void) { return asFUNCTION((&ref_setter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr sg(void) { return asFUNCTION(( &setter_gen<T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rsg(void) { return asFUNCTION((&ref_setter_gen<T, U, member_ptr>)); }
};

template <typename T, typename U>
GetSet<T, U> gs_id(U T::*) { return GetSet<T, U>(); }

#define GETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).g<&ClassName::member_name>())
#define REF_GETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rg<&ClassName::member_name>())
#define GETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).gg<&ClassName::member_name>())
#define REF_GETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rgg<&ClassName::member_name>())

#define SETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).s<&ClassName::member_name>())
#define REF_SETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rs<&ClassName::member_name>())
#define SETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).sg<&ClassName::member_name>())
#define REF_SETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rsg<&ClassName::member_name>())

template <typename T>
struct CCaller {
template <T ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr c(void) { return asFUNCTION(&(Caller<T>::f<ptr>)); }
template <T ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr g(void) { return asFUNCTION(&(GenCaller<T>::f<ptr>)); }
};

template <typename T>
CCaller<T> caller_id(T) { return CCaller<T>(); }

#define CALLER(ClassName, member_name) (::spw::caller_id(&ClassName::member_name).c< &ClassName::member_name >())
#define GEN_CALLER(ClassName, member_name) (::spw::caller_id(&ClassName::member_name).g< &ClassName::member_name >())
#define CALLER_PR(ClassName, member_name, Args, Return) asFUNCTION((::spw::Caller<Return (ClassName::*)Args>::f< &ClassName::member_name >))
#define GEN_CALLER_PR(ClassName, member_name, Args, Return) asFUNCTION((::spw::GenCaller<Return (ClassName::*)Args>::f< &ClassName::member_name >))

} // end namespace spw

#endif

Another python script, again, if four arguments aren't enough:

pointer_header = "<memory>" # which C++ header should be included
pointer_type = "std::shared_ptr<T>" # the name of the smart pointer parameterized on T
get_pointer = "(ptr.get())" # an expression that converts a smart pointer named ptr to T *
max_args = 4 # the maximum number of parameters to be processed

print """#ifndef AS_SMART_POINTER_WRAPPER
#define AS_SMART_POINTER_WRAPPER

#include <new>
#include "angelscript.h"
#include {0}
""".format(pointer_header)

print """namespace spw {

template <typename T> struct Default {
static T f(void) { return T(); }
};
template <typename T> struct Default<T &> {
static T & f(void) { return *static_cast<T *>(0); }
};

template <typename T> class Proxy {
public:
T value;
Proxy(T value) : value(value) {}
private:
Proxy(const Proxy &);
Proxy & operator=(const Proxy &);
};
"""

print """template <typename T, typename U, U T::*member_ptr>
U getter(const {0} & ptr) {{
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
return Default<U>::f();
}}
return {1}->*member_ptr;
}}

template <typename T, typename U, U T::*member_ptr>
const U & ref_getter(const {0} & ptr) {{
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
return Default<U &>::f();
}}
return {1}->*member_ptr;
}}

template <typename T, typename U, U T::*member_ptr>
void getter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{0} & ptr = *static_cast<{0} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
new (gen->GetAddressOfReturnLocation()) Proxy<U>({1}->*member_ptr);
}}
}}

template <typename T, typename U, U T::*member_ptr>
void ref_getter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{0} & ptr = *static_cast<{0} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
new (gen->GetAddressOfReturnLocation()) Proxy<U &>({1}->*member_ptr);
}}
}}

template <typename T, typename U, U T::*member_ptr>
void setter(const {0} & ptr, U value) {{
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
{1}->*member_ptr = value;
}}
}}

template <typename T, typename U, U T::*member_ptr>
void ref_setter(const {0} & ptr, const U & value) {{
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
{1}->*member_ptr = value;
}}
}}

template <typename T, typename U, U T::*member_ptr>
void setter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{0} & ptr = *static_cast<{0} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
{1}->*member_ptr = static_cast<Proxy<U> *>(gen->GetAddressOfArg(0))->value;
}}
}}

template <typename T, typename U, U T::*member_ptr>
void ref_setter_gen(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{0} & ptr = *static_cast<{0} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to access member of a null pointer");
}} else {{
{1}->*member_ptr = static_cast<Proxy<U &> *>(gen->GetAddressOfArg(0))->value;
}}
}}
""".format(pointer_type, get_pointer)

print """template <typename T> struct Caller {};
template <typename T> struct GenCaller {};
"""

typename_list = ", typename A0"
type_list = "A0"
parameter_list = ", A0 a0"
arg_list = "a0"
gen_arg_list = "\n static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value"

caller = """template <typename T, typename R{0}>
struct Caller<R (T::*)({1}){6}> {{
template <R (T::*fn)({1}){6}>
static R f({2} & ptr{3}) {{
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
return Default<R>::f();
}} else {{
return ({4}->*fn)({5});
}}
}}
}};
"""

gen_caller = """template <typename T{0}>
struct GenCaller<void (T::*)({1}){6}> {{
template <void (T::*fn)({1}){6}>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{2} & ptr = *static_cast<{2} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
}} else {{
({4}->*fn)({5});
}}
}}
}};

template <typename T, typename R{0}>
struct GenCaller<R (T::*)({1}){6}> {{
template <R (T::*fn)({1}){6}>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{2} & ptr = *static_cast<{2} *>(gen->GetObject());
if (!ptr) {{
AS_NAMESPACE_QUALIFIER asIScriptContext * ctx = AS_NAMESPACE_QUALIFIER asGetActiveContext();
ctx->SetException("Attempting to call member function of a null pointer");
}} else {{
new (gen->GetAddressOfReturnLocation()) Proxy<R>(({4}->*fn)({5}));
}}
}}
}};
"""

print caller.format("", "void", pointer_type, "", get_pointer, "", "")
print caller.format("", "void", pointer_type, "", get_pointer, "", " const")
print gen_caller.format("", "void", pointer_type, "", get_pointer, "", "")
print gen_caller.format("", "void", pointer_type, "", get_pointer, "", " const")

print caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, arg_list, "")
print caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, arg_list, " const")
print gen_caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, gen_arg_list, "")
print gen_caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, gen_arg_list, " const")

for i in range(1, max_args):
typename_list += ", typename A{0}".format(i)
type_list += ", A{0}".format(i)
parameter_list += ", A{0} a{0}".format(i)
arg_list += ", a{0}".format(i)
gen_arg_list += ",\n static_cast<Proxy <A{0}> *>(gen->GetAddressOfArg({0}))->value".format(i)

print caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, arg_list, "")
print caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, arg_list, " const")
print gen_caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, gen_arg_list, "")
print gen_caller.format(typename_list, type_list, pointer_type, parameter_list, get_pointer, gen_arg_list, " const")

print """template <typename T, typename U>
struct GetSet {
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr g(void) { return asFUNCTION(( &getter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rg(void) { return asFUNCTION((&ref_getter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr gg(void) { return asFUNCTION(( &getter_gen<T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rgg(void) { return asFUNCTION((&ref_getter_gen<T, U, member_ptr>)); }

template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr s(void) { return asFUNCTION((&setter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rs(void) { return asFUNCTION((&ref_setter <T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr sg(void) { return asFUNCTION(( &setter_gen<T, U, member_ptr>)); }
template <U T::* member_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr rsg(void) { return asFUNCTION((&ref_setter_gen<T, U, member_ptr>)); }
};

template <typename T, typename U>
GetSet<T, U> gs_id(U T::*) { return GetSet<T, U>(); }

#define GETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).g<&ClassName::member_name>())
#define REF_GETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rg<&ClassName::member_name>())
#define GETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).gg<&ClassName::member_name>())
#define REF_GETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rgg<&ClassName::member_name>())

#define SETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).s<&ClassName::member_name>())
#define REF_SETTER(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rs<&ClassName::member_name>())
#define SETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).sg<&ClassName::member_name>())
#define REF_SETTER_GEN(ClassName, member_name) (::spw::gs_id(&ClassName::member_name).rsg<&ClassName::member_name>())

template <typename T>
struct CCaller {
template <T ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr c(void) { return asFUNCTION(&(Caller<T>::f<ptr>)); }
template <T ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr g(void) { return asFUNCTION(&(GenCaller<T>::f<ptr>)); }
};

template <typename T>
CCaller<T> caller_id(T) { return CCaller<T>(); }

#define CALLER(ClassName, member_name) (::spw::caller_id(&ClassName::member_name).c< &ClassName::member_name >())
#define GEN_CALLER(ClassName, member_name) (::spw::caller_id(&ClassName::member_name).g< &ClassName::member_name >())
#define CALLER_PR(ClassName, member_name, Args, Return) asFUNCTION((::spw::Caller<Return (ClassName::*)Args>::f< &ClassName::member_name >))
#define GEN_CALLER_PR(ClassName, member_name, Args, Return) asFUNCTION((::spw::GenCaller<Return (ClassName::*)Args>::f< &ClassName::member_name >))

} // end namespace spw

#endif"""

Python code was developed on CPython 2.6.
Advertisement
This looks really great. I'm impressed as always with template magic you manage to conjure. :)

I'll take a closer look at this for version 2.22.2 and include it as an add-on.

It's definitely a major benefit not to have to declare and register the wrappers at two different locations.

I'll think about a way to avoid having the difference in the variable (?&) parameter types. Perhaps the reference and type can be passed in a simple pod-structure to C++ instead so it can be considered a single argument.

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

Well, it'd be easiest if generic functions could receive the type ids as additional parameters like native functions. Then the code would work as is. Maybe an engine property or an additional flag on top of asCALL_GENERIC? Though, I'm not sure how much practical difference supporting variable parameters would have. The rest of the wrappers take C++ code that would exist regularly, but the variable parameter functions have to be written specifically with AngelScript in mind, so if someone needed generic calling convention he would probably just write it that way in the first place.
Good point. Still I like consistency, so I'll keep this in mind for a 'possible' future change.

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

Took the time today to do proof of concept implementation of the variable parameter type with the struct argument option. Seems to work, or at least I was able to use it to get the scripthandle add-on to pass test_feature with AS_MAX_PORTABILITY defined on revision 1109.

scripthandle.cpp modification:

void construct(CScriptHandle * self, ::gw::VariableParameter v) {
Construct(self, v.object, v.type_id);
}

void ref_cast(CScriptHandle * self, ::gw::VariableParameter v) {
self->opCast(reinterpret_cast<void **>(v.object), v.type_id);
}

CScriptHandle * op_assign(CScriptHandle * self, ::gw::VariableParameter v) {
return &(self->opAssign(v.object, v.type_id));
}

bool op_equals(CScriptHandle * self, ::gw::VariableParameter v) {
return self->opEquals(v.object, v.type_id);
}

void RegisterScriptHandle_Generic(asIScriptEngine *engine)
{
int r;

r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", WRAP_OBJ_FIRST_PR(Construct, (CScriptHandle *), void), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", WRAP_OBJ_FIRST_PR(Construct, (CScriptHandle *, const CScriptHandle &), void), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", WRAP_OBJ_FIRST_PR(Destruct, (CScriptHandle *), void), asCALL_GENERIC); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", WRAP_OBJ_FIRST(construct), asCALL_GENERIC); assert( r >= 0 );

r = engine->RegisterObjectMethod("ref", "ref &opAssign(const ref &in)", WRAP_MFN(CScriptHandle, operator=), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", WRAP_MFN_PR(CScriptHandle, opEquals, (const CScriptHandle &) const, bool), asCALL_GENERIC); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("ref", asBEHAVE_REF_CAST, "void f(?&out)", WRAP_OBJ_FIRST(ref_cast), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("ref", "ref &opAssign(const ?&in)", WRAP_OBJ_FIRST(op_assign), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", WRAP_OBJ_FIRST(op_equals), asCALL_GENERIC); assert( r >= 0 );
}

void RegisterScriptHandle(asIScriptEngine *engine)
{
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
RegisterScriptHandle_Generic(engine);
else
RegisterScriptHandle_Native(engine);
}


New Python code:

max_args = 4 # the maximum number of parameters to be processed

print """#ifndef AS_GEN_WRAPPER_H
#define AS_GEN_WRAPPER_H

#include "angelscript.h"
#include <new>

namespace gw {

template <typename T> class Proxy {
public:
T value;
Proxy(T value) : value(value) {}
static T cast(void * ptr) {
return reinterpret_cast<Proxy<T> *>(&ptr)->value;
}
private:
Proxy(const Proxy &);
Proxy & operator=(const Proxy &);
};

struct VariableParameter {
void * object;
int type_id;

VariableParameter(void * obj, int type) : object(obj), type_id(type) {}
};

template <typename T> struct Arg {
static T arg(asIScriptGeneric * gen, int i) {
return static_cast<Proxy <T> *>(gen->GetAddressOfArg(i))->value;
}
};

template <> struct Arg<VariableParameter> {
static VariableParameter arg(asIScriptGeneric * gen, int i) {
return VariableParameter(gen->GetArgAddress(i), gen->GetArgTypeId(i));
}
};

template <typename T> struct Wrapper {};
template <typename T> struct ObjFirst {};
template <typename T> struct ObjLast {};
"""

typename_list = "typename A0"
type_list = "A0"
arg_list = "\n Arg<A0>::arg(gen, 0)"
new_exp = "new (gen->GetAddressOfReturnLocation()) Proxy<R>"
obj_exp = "static_cast<T *>(gen->GetObject())->*"
obj_arg_exp = "\n Proxy<T>::cast(gen->GetObject())"

template = """template <{0}{1}>
struct {9}<{2} ({3}*)({7}){4}> {{
template <{2} ({3}*fp)({7}){4}>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {{
{5}(({6}fp)({8}));
}}
}};
"""

print template.format("", "", "void", "", "", "", "", "void", "", "Wrapper")
print template.format("typename R", "", "R", "", "", new_exp, "", "void", "", "Wrapper")
print template.format("typename T", "", "void", "T::", "", "", obj_exp, "void", "", "Wrapper")
print template.format("typename T, typename R", "", "R", "T::", "", new_exp, obj_exp, "void", "", "Wrapper")
print template.format("typename T", "", "void", "T::", " const", "", obj_exp, "void", "", "Wrapper")
print template.format("typename T, typename R", "", "R", "T::", " const", new_exp, obj_exp, "void", "", "Wrapper")

print template.format("typename T", "", "void", "", "", "", "", "T", obj_arg_exp, "ObjFirst")
print template.format("typename T, typename R", "", "R", "", "", new_exp, "", "T", obj_arg_exp, "ObjFirst")
print template.format("typename T", "", "void", "", "", "", "", "T", obj_arg_exp, "ObjLast")
print template.format("typename T, typename R", "", "R", "", "", new_exp, "", "T", obj_arg_exp, "ObjLast")

for i in range(0, max_args):
print template.format("", typename_list, "void", "", "", "", "", type_list, arg_list, "Wrapper")
print template.format("typename R, ", typename_list, "R", "", "", new_exp, "", type_list, arg_list, "Wrapper")
print template.format("typename T, ", typename_list, "void", "T::", "", "", obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, typename R, ", typename_list, "R", "T::", "", new_exp, obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, ", typename_list, "void", "T::", " const", "", obj_exp, type_list, arg_list, "Wrapper")
print template.format("typename T, typename R, ", typename_list, "R", "T::", " const", new_exp, obj_exp, type_list, arg_list, "Wrapper")

print template.format("typename T, ", typename_list, "void", "", "", "", "", "T, " + type_list, obj_arg_exp + "," + arg_list, "ObjFirst")
print template.format("typename T, typename R, ", typename_list, "R", "", "", new_exp, "", "T, " + type_list, obj_arg_exp + "," + arg_list, "ObjFirst")
print template.format("typename T, ", typename_list, "void", "", "", "", "", type_list + ", T", arg_list + "," + obj_arg_exp, "ObjLast")
print template.format("typename T, typename R, ", typename_list, "R", "", "", new_exp, "", type_list + ", T", arg_list + "," + obj_arg_exp, "ObjLast")

typename_list += ", typename A{0}".format(i + 1)
type_list += ", A{0}".format(i + 1)
arg_list += ",\n Arg<A{0}>::arg(gen, {0})".format(i + 1)

print """template <typename T>
struct Id {
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr f(void) { return asFUNCTION(&(Wrapper<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr of(void) { return asFUNCTION(&(ObjFirst<T>::f<fn_ptr>)); }
template <T fn_ptr> AS_NAMESPACE_QUALIFIER asSFuncPtr ol(void) { return asFUNCTION(&(ObjLast<T>::f<fn_ptr>)); }
};

template <typename T>
Id<T> id(T fn_ptr) { return Id<T>(); }

#define WRAP_FN(name) (::gw::id(name).f< name >())
#define WRAP_MFN(ClassType, name) (::gw::id(&ClassType::name).f< &ClassType::name >())
#define WRAP_OBJ_FIRST(name) (::gw::id(name).of< name >())
#define WRAP_OBJ_LAST(name) (::gw::id(name).ol< name >())

#define WRAP_FN_PR(name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (*)Parameters>::f< name >))
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::f< &ClassType::name >))
#define WRAP_OBJ_FIRST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjFirst<ReturnType (*)Parameters>::f< name >))
#define WRAP_OBJ_LAST_PR(name, Parameters, ReturnType) asFUNCTION((::gw::ObjLast<ReturnType (*)Parameters>::f< name >))

} // end namespace gw

#endif"""
Cool. Thanks for adding support for this too.

Though I'm not quite sure this will be fully portable. Depending on the OS and compiler the VariableParameter structure will not always be passed the same way the two parameters is today. This means the native function that receives a VariableParameter cannot be used without the wrapper, unless I change the library to always pass the ? args as a VariableParameter structure.

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

Yeah, the idea was to see if you decide to change the mechanism AngelScript uses from the void * and type id arguments to a combined structure like you said at the end of your first response, if the code could be modified to account for that - which it seems it can. Even without that, it does simplify writing the wrappers for the variable parameter functions, but that's more of a happy accident than what I was looking at.
I finally got the time to give these a try in order to include them in the SDK, and I quickly discovered that the code relies quite heavily on C++11 features. While this is not a bad thing, and I personally like keeping up to date with new language feature it does make it difficult to include it as a standard add-on in AngelScript at this moment as C++11 still isn't all that widespread.

Instead I put together the files in a small package and uploaded it to my site:

http://www.angelcode.com/angelscript/resources.html


Regards,
Andreas

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

It shouldn't require C++11, I got it to work with MSVC 2008. The smart pointer wrappers use std::shared_ptr as an example, but you can switch out for boost::shared_ptr, or whatever other smart pointer you like.
Have you thought about using BOOST_PP for automatic expansion of the wrapper, it would avoid the tedious step of having to generate the wrapper class for N arguments, as you could just use BOOST_PP to do it for you?

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

This topic is closed to new replies.

Advertisement