Advertisement

Class Members Unregistering

Started by January 09, 2021 07:32 PM
14 comments, last by WitchLord 3 years, 8 months ago

I want to simulate a class hierarchy using function calls, but derived classes can hide some methods of the base class, so I need way to unregister already registered members

RegisterBaseClass()
{
    RegisterMember1();
    RegisterMember2();
}

RegisterDerivedClass()
{
    RegisterBaseClass();
    
    UnregisterMember1(); // By declaration?
    
    RegisterMember3();
    RegisterMember4();
}

I need this for automatic binding generation, so I always have information which members of the base class were hidden (we use Doxygen to get info about classes)

Currently we register all members of all classes in single function but compilation of the project is VERY long and even had to split the generated code into many files so that some compilers (MinGW32) would not crash due to lack of memory

https://github.com/urho3d/Urho3D/tree/master/Source/Urho3D/AngelScript

https://github.com/urho3d/Urho3D/blob/master/Source/Urho3D/AngelScript/Generated_Members_Cn_Cz.cpp

Instead of first registering the members and then trying to unregister them, why don't you pass the list of members that shouldn't be registered to RegisterBaseClass?

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

I considered this option, but it will increase the size of the generated code twice because I need to insert a search in the list before registering each method

if (!CONTAINS(list, id1))
   Register1();
if (!CONTAINS(list, id2))
   Register2();
...

I started reworking the existing bindings in order to reduce their size. The size will decrease, but not as much as I would like.

Since you know at the time of the code generation which class members can be hidden by derived classes you only need to add an if for these, thus minimizing the increase of the generated code. You could probably also write it in such a way so that instead of passing a list of members you would just pass the name of the derived class, and thus do only a single if statement (and only for those bases classes whose members are hidden by any derived class).

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

Users can link the engine as a library and inherit their own classes from the engine's classes. The generator don't know anything about such classes.

Comparsion operator:

bool operator ==(const asSFuncPtr& a, const asSFuncPtr& b)

{

   for (size_t i = 0; i < sizeof(a.ptr.dummy); i++)

   {

       if (a.ptr.dummy[i] != b.ptr.dummy[i])

           return false;

   }



   return a.flag == b.flag;

}

=========

struct Bas

{

   void X() { }

};

struct Chi : public Bas

{

};

asMETHODPR(Bas, X, (), void) == asMETHODPR(Chi, X, (), void)

======

struct Bas
{
    void X() { }
};

struct Bas2
{
};

struct Chi : public Bas, Bas2
{
};

asMETHODPR(Bas, X, (), void) != asMETHODPR(Chi, X, (), void)

=======

So usage asMETHODPR(BASE_CLASS, BASECLASSMETHOD, (), void) for registering methods of base class in separate functions cause crash in some situation [but asMETHODPR(DERIVED_CLASS, BASECLASSMETHOD, (), void) works]

https://github.com/1vanK/Urho3D/blob/master/Source/Urho3D/AngelScript/Generated_Members_Graphics.cpp

void CollectMembers_AnimatedModel(MemberCollection& members)
{
    CollectMembers_StaticModel(members);

    Remove(members.methods_, "ResourceRef StaticModel::GetModelAttr() const");
    Remove(members.methods_, "bool Animatable::LoadJSON(const JSONValue& source) override");
    Remove(members.methods_, "bool Animatable::LoadXML(const XMLElement& source) override");

    members.methods_.Push(...);
    

MemberCollection store pointers asMETHODPR(…)

=======

You could probably also write it in such a way so that instead of passing a list of members you would just pass the name of the derived class, and thus do only a single if statement (and only for those bases classes whose members are hidden by any derived class).

If use templates:

template <class T> void RegisterUIElement(asIScriptEngine* engine, const char* className, bool isSprite = false)
{
    // Base classes
    RegisterAnimatable<T>(engine, className);
        
    engine->RegisterObjectMethod(className, "void SetSize(int, int)", asMETHODPR(T, SetSize, (int, int), void), asCALL_THISCALL);

    if (!isSprite)
        engine->RegisterObjectMethod(className, "void SetPosition(int, int)", asMETHODPR(T, SetPosition, (int, int), void), asCALL_THISCALL);
}

just not compile because compiler considers asMETHODPR(T, SetPosition, (int, int), void) but this function is hidden.

I can write

if (!isSprite)
        engine->RegisterObjectMethod(className, "void SetPosition(int, int)", asMETHODPR(UIElement, SetPosition, (int, int), void), asCALL_THISCALL);

but then I am facing the problem described at the beginning of the post

Advertisement

Forgot to add that using Generic Autowrappers WRAP_MFN_PR(DERIVED_CLASS, BASE_CLASS_METHOD, p, r) cause errors in some compilers (emscripten), which just don't match template if used deriven class instead base class with the metod

1vanK said:
So usage asMETHODPR(BASE_CLASS, BASECLASSMETHOD, (), void) for registering methods of base class in separate functions cause crash in some situation [but asMETHODPR(DERIVED_CLASS, BASECLASSMETHOD, (), void) works]

Yes, you should always take the address of the method from the point of view of the actual type you're registering so you get the correct resolution of virtual and non-virtual methods.

The article in the manual does this by using templates http://www.angelcode.com/angelscript/sdk/docs/manual/doc_adv_class_hierarchy.html

The article obviously isn't as advanced as your code, and doesn't have a case of hidden members.​ Maybe I'll update it with some ideas from your code ?

1vanK said:
just not compile because compiler considers asMETHODPR(T, SetPosition, (int, int), void) but this function is hidden.

Maybe compile time evaluated expressions will help here. I haven't used c++17 much yet though, so I can't say if it will work, or even if most compilers support it to begin with.

https://www.codingame.com/playgrounds/2205/7-features-of-c17-that-will-simplify-your-code/constexpr-if

1vanK said:
Forgot to add that using Generic Autowrappers WRAP_MFN_PR(DERIVED_CLASS, BASE_CLASS_METHOD, p, r) cause errors in some compilers (emscripten), which just don't match template if used deriven class instead base class with the metod

Can you show the error message and the code it fails to compile? I've seen similar compatibility issues before and it may require some tweaks to the code in aswrappedcall.h. I don't use emscripten myself so I'd need some help in figuring out how to solve this problem.

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

> I don't use emscripten myself

Same problem in MinGW.

Actually VS also not works with generated aswrappedcall.h but this can be fixed:

// Original
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< &ClassType::name >))

// Fixed
#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFUNCTION((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< AS_METHOD_AMBIGUITY_CAST(ReturnType (ClassType::*)Parameters)(&ClassType::name) >))

But for MinGW this not helps.

> Can you show the error message and the code it fails to compile?

This take some time

Visual studio with unmodified macro:

struct Bas
{
    void X() {}
};

struct Ch : public Bas
{
};

void Reg(asIScriptEngine* engine)
{
    WRAP_MFN_PR(Bas, X, (), void); // Works
    WRAP_MFN_PR(Ch, X, (), void); / Error
}

Error message:

error C2672: 'asFunctionPtr': no matching overloaded function found
error C2893: Failed to specialize function template 'void gw::Wrapper<void (__cdecl Urho3D::Ch::* )(void)>::f(asIScriptGeneric *)'
message : see declaration of 'gw::Wrapper<void (__cdecl Urho3D::Ch::* )(void)>::f'
message : With the following template arguments:
fatal error C1903: unable to recover from previous error(s); stopping compilation

MinGW shows same kind message (function just not found) and fix not helped

This topic is closed to new replies.

Advertisement