#include "angelscript.h" #include "scriptstdstring.h" #include "scripthelper.h" #include #include #include 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 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(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)), 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(console); \n" " addListener(x, ET_READLINE); \n" " addListener(cast(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(); }