#include "angelscript.h"
#include "scriptstdstring.h"
#include "scripthelper.h"
#include <stdio.h>
#include <iostream>
#include <stdexcept>
using namespace std;
class EventSource
{
public:
EventSource() {refCount = 1; value = 42;};
virtual ~EventSource() {}
virtual void AddRef() {refCount++;}
virtual void Release() {if( --refCount == 0 ) delete this;}
int refCount;
int value;
};
class ASConsole : public EventSource
{
public:
static ASConsole *factory() { return new ASConsole(); }
};
template<class A, class B> B* ASRefCast(A* a)
{
// If the handle already is a null handle, then just return the null handle
if (a==NULL) return NULL;
// Now try to dynamically cast the pointer to the wanted type
B* b = dynamic_cast<B*>(a);
if (b!=NULL) {
// Since the cast was made, we need to increase the ref counter for the returned handle
b->AddRef();
}
cout << "ASRefCast: returning " << hex << b << endl;
return b;
}
void Assert(bool condition)
{
if (!condition) {
int line;
const char* section;
asGetActiveContext()->GetLineNumber(0, &line, §ion);
cerr << "Assertion failed; Section " << section << " line " << line << cout;
}
}
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 addListener(EventSource* source, int mask) {
cout << "addListener: source = " << hex << source << endl;
cout << "addListener: source.value = " << (int)source->value << endl;
cout << endl;
cout << endl;
}
bool Test()
{
bool fail = false;
int r;
asIScriptEngine *engine;
// http://www.gamedev.n...sting-directly/
{
ASConsole* c = new ASConsole();
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_CDECL);
RegisterStdString(engine);
engine->RegisterObjectType("EventSource", 0, asOBJ_REF);
engine->RegisterObjectBehaviour("EventSource", asBEHAVE_ADDREF, "void f()", asMETHOD(EventSource, AddRef), asCALL_THISCALL);
engine->RegisterObjectBehaviour("EventSource", asBEHAVE_RELEASE, "void f()", asMETHOD(EventSource, Release), asCALL_THISCALL);
engine->RegisterObjectProperty("EventSource", "int value", asOFFSET(EventSource, value));
engine->RegisterObjectType("ASConsole", 0, asOBJ_REF);
engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_FACTORY, "ASConsole @f()", asFUNCTION(ASConsole::factory), asCALL_CDECL);
engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_ADDREF, "void f()", asMETHOD(ASConsole, AddRef), asCALL_THISCALL);
engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_RELEASE, "void f()", asMETHOD(ASConsole, Release), asCALL_THISCALL);
engine->RegisterObjectBehaviour("ASConsole", asBEHAVE_IMPLICIT_REF_CAST, "EventSource@ f()",
asFUNCTION((ASRefCast<ASConsole, EventSource>)), asCALL_CDECL_OBJLAST);
engine->RegisterGlobalFunction("void addListener(EventSource &inout, const int &in)", asFUNCTION(addListener), asCALL_CDECL);
asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
mod->AddScriptSection("test",
"enum E { ET_READLINE = 24 } \n"
"ASConsole @console;\n"
"void main() \n"
"{ \n"
" EventSource@ x = cast<EventSource>(console); \n"
" addListener(x, ET_READLINE); \n"
" addListener(cast<EventSource>(console), ET_READLINE); \n"
"} \n");
r = mod->Build();
void** consoleVarAddr = (void**)mod->GetAddressOfGlobalVar(mod->GetGlobalVarIndexByName("console"));
*consoleVarAddr = c;
if( r < 0 )
throw runtime_error("Compilation failed");
r = ExecuteString(engine, "main()", mod);
if( r != asEXECUTION_FINISHED )
throw runtime_error("Execution failed");
engine->Release();
}
return fail;
}
int main(int argc, char** argv) {
Test();
}