Hi!
I'm trying to figure out how to implement an interface and its implementation inside the application code. I want to have an interface App
like:
interface App {
void Foo();
void Bar();
};
A user has to write a script with Init
function inside that accepts a reference to App
:
// Somewhere in user code.
void Init(App @ app) {
if(some_condition) app.Bar();
if(another_condition) app.Foo();
...
}
I need the interface App
to hide the detail of the actual implementation of the interface between the application and the user-provided script. It means that there is something like:
namespace appdetails {
class ActualApp : App {
void Foo() override {...}
void Bar() override {...}
...
};
void CallInit(ActualApp @ app) {
::Init(app); // Init() is provided by user.
}
}
I don't want to describe App
and appdetails::ActualApp
in script files. I want to define them in the application code. Something like:
engine->RegisterInterface("App", ...);
engine->RegisterInterfaceMethod("App", "void Foo()");
engine->RegisterInterfaceMethod("App", "void Bar()");
...
engine->SetDefaultNamespace("appdetails");
engine->RegisterObjectType("ActualApp", 0, asOBJ_REF);
engine->RegisterObjectBehaviour("ActualApp", asBEHAVE_ADDREF, ...);
engine->RegisterObjectBehaviour("ActualApp", asBEHAVE_RELEASE, ...);
engine->RegisterObjectMethod("ActualApp", "void Foo()");
engine->RegisterObjectMethod("ActualApp", "void Bar()");
But I don't see any way of telling the engine that ActualApp
implements App
interface.
The only method I've found in the doc is to implement opImplCast
for ActualApp
type. Something like:
class App {
public:
virtual ~App();
int AddRef();
int Release();
virtual void Foo() = 0;
virtual void Bar() = 0;
...
};
class ActualApp : public App {
void Foo() override {...}
void Bar() override {...}
static App * castToApp(ActualApp * obj) {
App * result = obj;
result->AddRef();
return result;
}
};
...
engine->SetDefaultNamespace("appdetails");
engine->RegisterObjectType("ActualApp", 0, asOBJ_REF);
...
engine->RegisterObjectMethod("ActualApp", "App @ opImplCast()",
asFUNCTION(ActualApp::castToApp), asCALL_CDECL_OBJLAST);
But in that case, I get an application crash somewhere inside as_scriptengine.cpp source code. I suppose it's because AngelScript expects that the opImplCast
returns an object derived from asIScriptObject, but that isn't my case.
So I decided that there is no way to define an interface and its implementation in the application code. I'm right? Or there is some way to do that?