🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Application Class Implementing interface

Started by
12 comments, last by MindOfTony 6 days, 5 hours ago

I want to register an application type that implements an application registered interface, I have a system in mind for uploading stuff to the gpu, where I have the script implement an ISerializable interface that can write its contents into an IWritableBuffer interface, so that this can be used to send data to the GPU (GPU buffers would implement IWritableBuffer), and also be able to write to files (via a method to retrieve the raw file buffer).

Advertisement

I didn't identify a question in your post, so I'm not sure what your doubt is or even if you have a doubt at all.

The angelscript interface and C++ interface are unfortunately not interchangeable, so it is not possible for a script class to implement a C++ interface directly.

You can however register a script interface from the application so you can ensure the script class implements the required methods, and then implement C++ method that takes an asIScriptClass (knowing it implements the script interface).

Taking this a step further (though probably unnecessary) you can implement inheritance of C++ class for a script class via composition.

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

@WitchLord Sorry if i phrased it wrongly, the question is I have registered an interface via RegisterInterface, and I want to register a type, but I want that type to implement that interface. So i want to register a type to angelscript that I can tell the engine implements a specific interface that i registered to the engine.

so

C++
RegisterInterface("IChr")
RegisterInterfaceMethods("IChr",void run()");

class Chr
{
void run(){}
static Register(scriptengine);//RegisterClassObject with inheritance like class Chr : interface IChr with functions linked from RegisterInterface("IChr") and RegisterInterfaceMethods for Angelscript.
;

then push objects from C++ to Angelscript
with array<Chr> objects
setArgObject(objects)

Angelscript
void UpdateObjects(array<IChr @>chr)
{
//forloop chr
chr.run();
}

void CreateObject()
{
pushtoCPPobjects(Chr());
}

is it something like this you were thinking of?

Yeah kind of like this, the snippet is a bit confusing but I want an application registered class to implement a registered interface, so I can use with interface specific functions

@MindOfTony I am freetyping as I am at my tablet, sorry about that. 😉
simpler example then
static void Register(asIScriptEngine *engine)
engine->RegisterObjectType("Chr : IChr", sizeof(Chr), flag);//register the Angelscript object as a derivative of interface
engine->RegisterObjectMethod("Chr", “void run() override”, funcPointer, calltype);
//register the C++ class function as the override for the interface run method

I'm sorry @mindoftony and @zervoxe , but that doesn't work.

RegisterInterface registers a script interface, same as if declared within the script. It's not possible for C++ classes to implement a script interface. The underlying ABI is simply not compatibly, C++ works with native code and virtual function tables, while the script classes relies on the data structure in the asCScriptObject.

If you really want to allow both script classes and C++ classes to be passed to the same serialization object, I suggest you do that by using the variable argument type, ?&. This will allow the C++ implementation to take any type, determine which type it is based on the typeid that is sent along with the address of the value, and if it is a script type (i.e. typeId & asTYPEID_SCRIPTOBJECT) the value can be cast to asIScriptObject, on which the script methods can be invoked. If it is not a script object, then determine the type of the application registered type with GetTypeInfoById. If the application type is known to implement the C++ ISerializable interface the value can then be cast to that interface and further processed.

Using the variable argument type would be giving up on the compile time verification that the value really can be serialized, but that is perhaps not that important.

Another option is to implement two different functions. One function would allow sending script types that implement the script interface ISerializable. And the other would allow sending application types that implement the C++ interface ISerializable.

To tell AngelScript that a registered type can be cast to another registered type (i.e. the C++ interface ISerializable) you would register an opImplCast method for the valid cast.

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

WitchLord said:

I'm sorry @mindoftony and @zervoxe , but that doesn't work.

RegisterInterface registers a script interface, same as if declared within the script. It's not possible for C++ classes to implement a script interface. The underlying ABI is simply not compatibly, C++ works with native code and virtual function tables, while the script classes relies on the data structure in the asCScriptObject.

If you really want to allow both script classes and C++ classes to be passed to the same serialization object, I suggest you do that by using the variable argument type, ?&. This will allow the C++ implementation to take any type, determine which type it is based on the typeid that is sent along with the address of the value, and if it is a script type (i.e. typeId & asTYPEID_SCRIPTOBJECT) the value can be cast to asIScriptObject, on which the script methods can be invoked. If it is not a script object, then determine the type of the application registered type with GetTypeInfoById. If the application type is known to implement the C++ ISerializable interface the value can then be cast to that interface and further processed.

Using the variable argument type would be giving up on the compile time verification that the value really can be serialized, but that is perhaps not that important.

Another option is to implement two different functions. One function would allow sending script types that implement the script interface ISerializable. And the other would allow sending application types that implement the C++ interface ISerializable.

To tell AngelScript that a registered type can be cast to another registered type (i.e. the C++ interface ISerializable) you would register an opImplCast method for the valid cast.

I wasn't asking if it was possible, I was interested in finding out what he meant so that I could give suggestions, which you have now done. 🙂

My thoughts was more like registering the Application class with a factory instead of using Interface at all.

RegisterInterface registers a script interface, same as if declared within the script. It's not possible for C++ classes to implement a script interface. The underlying ABI is simply not compatibly, C++ works with native code and virtual function tables, while the script classes relies on the data structure in the asCScriptObject.

I dont want a c++ type to implement a script interface, I want a registered angelscript type. heres my example.

class VertexBuffer {...}
void VB_Write(bytes_or_smth param, VertexBuffer* obj) {...}
engine->RegisterInterface("ISerializable");
engine→RegisterInterface("IBuffer");
engine->RegisterInterfaceMethod("ISerializable", "void serialize(IBuffer@ buffer)");
engine→RegisterInterfaceMethod("IBuffer", "void write(bytes or smth)");
engine->RegisterObjectType("VertexBuffer : IBuffer",...);
/*the above line should tell the engine that for the newly registered type, it can be treated as a type in angelscript that implements the IBuffer interface, hence before any building can take place all the interfaces have methods have to be registered*/
engine->RegisterObjectMethod("VertexBuffer", "void write(...)", ..., asCALL_CDECL_OBJLAST);

I don't think this would require ABI compatibility and it is just for a better API and to leverage the static typing. using ?& can be nice but for every new serializble app type that you add you have to change all the buffers serialize methods and that can get pretty tedious quickly, it also defeats the point of having the language statically typed. Unless it's not possible to call functions from app registered types this seems like the nicest and most consistent way imo. another option would be to have a registry or map of app types that implement these interfaces and the function pointers for each interface method, but this would also limit what the script writer can do regarding interfaces


This should work for interfaces because they're just interfaces, they don't have data and only require functions to be implemented

So you don't want script classes to implement the C++ interfaces.

You only want to tell AngelScript that a C++ type is implementing a specific C++ interface, so the type can be cast to that interface?

Correct so far?

Then you should not use the RegisterInterface. You should register the C++ interface with RegisterObjectType, Then register the opImplCast method on the type that should be castable to the interface. AngelScript doesn't really know if the types you register are actually classes, interfaces, or structs. They are all treated the same way.

(see links in my previous post)

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

Advertisement