C++ multiple inheritance binding?


#1

It seems there’s only single inheritance in SkookumScript, when it comes to multiple inheritance C++ classes, what’s the proper way to bind them?


#2

Yes, SkookumScript uses single inheritance - primarily due to keeping things streamlined and simple. We also plan to add something like mixins/traits in the future.

For now there are a few different things you can do for hooking up C++ classes that have multiple inheritance.

  • The simplest mechanism is to just treat such C++ classes as single inheritance classes at the scripting level. You could still wrap up the C++ bindings for one of the superclasses in a routine such that you could add them to multiple script classes at the C++ level creating your own mixin capability.
  • We have found that using a entity+component code reuse practice - such as used by Unreal Engine 4 (and every game engine that I have used since 2001) - gives a lot more control capability and dynamic changeability. In this mechanism, you have an accessor on your entity object that returns a reference to an internally stored component that specializes in a particular capability - such as physics, AI, navigation, animation, etc. Then you just use the specialized routines of that component which is a different class in the scripting system. This works best when the C++ data structures are actually using the entity+component mechanism themselves though you can also simulate the same effect (without dynamic changeability) at the script level even if the C++ level just uses multiple inheritance.

I hope that helps and feel free to supply additional specifics if you would like a more tailored solution to what you are trying to accomplish.


Mixins and Interfaces
#3

Thanks for your answer, Noolarch! But I’m afraid I failed to understand how to apply your suggestions in to a real world scenario.

Take UTBot from UnrealTournament as example:

class UNREALTOURNAMENT_API AUTBot : public AAIController, public IUTTeamInterface

In SkookumScript class TeamManager I has method:
get_team_num(UTTeamInterface team) Integer

How can I pass a UTBot ( inherit from AIController ) to the get_team_num method?


#4

[I’m using our current naming conventions which may be available by the time you read this or will be soon.]

Given your example scenario, assuming that AUTBot, AAIController and IUTTeamInterface are already UE classes known to SkookumScript with SkUE prefixes and let’s also assume that the script class AUTBot is a subclass of AAIController then you would create SkookumScript code similar to this:

!bot: AUTBot.named("my_bot1")

// Calling AAIController@aicontroller_command()
bot.aicontroller_command

// Calling custom AUTBot@team_interface() IUTTeamInterface
!bot_iteam: bot.team_interface
!team_num:  TeamManager.get_team_num(bot_iteam)

Since bot at the C++ level is a SkInstance that stores a weak pointer to an AUTBot we just need to make a new SkInstance with the same pointer and the IUTTeamInterface SkookumScript class.

This is similar to the entity/component component technique I mentioned earlier - which is an example of composition over inheritance - but it just reclasses the entire reference rather than returning a contained object.

The C++ code for AUTBot@team_interface() IUTTeamInterface would look something like this:

static void mthd_team_interface(SkInvokedMethod * scope_p, SkInstance ** result_pp)
  {
  if (result_pp)
    {
    *result_pp = SkUEIUTTeamInterface::new_instance(scope_p->this_as<SkUEAUTBot>());  
    }
  }

In the future we can also make a SkookumScript method that allows an arbitrary Entity (or some other class) to copy the weak reference of an existing UE object and give it a new SkookumScript class. Then you wouldn’t need to write any C++ code. So it could look like this:

!bot_iteam: IUTTeamInterface!reclass(bot)

In the farther future we will add trait functionality to SkookumScript to do this more properly/elegantly.

This is fairly tricky so please let me know if this makes sense and if not I can try to give more examples and clarification.