🎉 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!

SIGSEGV in Generic Wrappers for derived class methods, but not base methods

Started by
4 comments, last by vballDrummer 4 years, 3 months ago

I have a derived class from a base class registered as in the template example. If I call a base class method, everything is fine. If I call a method of the derived class I get a SEGV in the Wrappers.

I am on (Ubuntu/ARM64 using generic wrappers)

In the leadup to Execute() I create a script on the fly that looks like:

std::string script = "DerivedClass m4808(5,0);int cowboy(){ m4808.setRPM(10); Print(\"CC Command sent\r\n\"); return 0; }"

The sequence of preparing the module is:

// Get/Create the module, add the script and build/compile
asIScriptModule* seMod = gSE.getEngine().GetModule(SE_COWBOY_MODULE, asGM_ALWAYS_CREATE); assert(seMod != nullptr);
 
if (seMod->AddScriptSection(SE_COWBOY_SECTION, script.c_str()) < 0)
{
LOG_F(WARNING, "Unable to add script section: %s", SE_COWBOY_SECTION);
return; //seStatus::ERROR_FUNCTION_NOT_FOUND;
}

if (seMod->Build() < 0)
{
LOG_F(WARNING, "Unable to build module: %s", SE_COWBOY_MODULE);
return; // seStatus::ERROR_FUNCTION_NOT_FOUND;
}

if (m_pMainCtx->Prepare(gSE.getEngine().GetModule(SE_COWBOY_MODULE)->GetFunctionByDecl(SE_COWBOY_FUNCTION)) < 0)
{
LOG_F(WARNING, "Unable to prepare script function: %s", SE_COWBOY_MODULE);
return; // seStatus::ERROR_FUNCTION_NOT_FOUND;
}

// execute the script
if (m_pMainCtx->Execute() == asEXECUTION_FINISHED)
{ …  }

The application SEGVs during the Execute() with

Thread
3 "ScriptEngine" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fb6b1ed60 (LWP 1777)]

gw::Wrapper<MotorStatus (DerivedClass::*)(double, double, short, short)>::f<&amp;amp;DerivedClass::setRPM> (gen=0x7fb6b1d690) at ../include/as_add_on/autowrapper/aswrappedcall.h:456
456   new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(

and the aswrappedcall is:
(In the template, gen* is not null, but A0, A1, A2, A3 look like garbage)

template <typename T, typename R, typename A0, typename A1, typename A2, typename A3>
struct Wrapper<R (T::*)(A0, A1, A2, A3)> {
template <R (T::*fp)(A0, A1, A2, A3)>
static void f(AS_NAMESPACE_QUALIFIER asIScriptGeneric * gen) {
 new (gen->GetAddressOfReturnLocation()) Proxy<R>((static_cast<T *>(gen->GetObject())->*fp)(
   static_cast<Proxy <A0> *>(gen->GetAddressOfArg(0))->value,
   static_cast<Proxy <A1> *>(gen->GetAddressOfArg(1))->value,
   static_cast<Proxy <A2> *>(gen->GetAddressOfArg(2))->value,
   static_cast<Proxy <A3> *>(gen->GetAddressOfArg(3))->value));
}
};

Advertisement

Please show how you have registered the class and the method too.

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

Reading further, with “class Derived : public Base {…}”, I think I need to “establish the relationship”. That means I’ll have to switch from asOBJ_VALUE to asOBJ_REF and I don’t know the impact to the code or scripts. I also need to implement the Factory, Addref and Release behaviors, correct? Do the factory functions replace the asBEHAVE_CONSTRUCT and asBEHAVE_DESTRUCT I have below?

I am using asGENERIC and Wrappers (on arm64)

Registration of objects are:

// Register the objects (classes).
// Base
r = m_pEngine->RegisterObjectType("Base", sizeof(Base), asOBJ_VALUE); assert(r >= 0);
r = m_pEngine->RegisterObjectBehaviour("Base", asBEHAVE_CONSTRUCT, "void f(int axisId, int memMapStageIdx)", WRAP_CON(Base, (int axisId, int memMapStageIdx)), asCALL_GENERIC); assert(r >= 0);
r = m_pEngine->RegisterObjectBehaviour("Base", asBEHAVE_DESTRUCT, "void f()", WRAP_DES(Base), asCALL_GENERIC); assert(r >= 0);
RegisterBaseMethods<Base>(m_pEngine, "Base");
           
           
// Derived
r = m_pEngine->RegisterObjectType("Derived", sizeof(Derived), asOBJ_VALUE); assert(r >= 0);
r = m_pEngine->RegisterObjectBehaviour("Derived", asBEHAVE_CONSTRUCT, "void f(int axisId, int memMapStageIdx)", WRAP_CON(Derived, (int axisId, int memMapStageIdx)), asCALL_GENERIC); assert(r >= 0);
r = m_pEngine->RegisterObjectBehaviour("Derived", asBEHAVE_DESTRUCT, "void f()", WRAP_DES(Derived), asCALL_GENERIC); assert(r >= 0);
RegisterDerivedMethods<Derived>(m_pEngine, "Derived");

and

 template <class T>
void RegisterBaseMethods(asIScriptEngine* engine, const char* type)
{
    int r;
  
// arm64 native calling convention not supported ... using generic
r = engine->RegisterObjectMethod(type, "int test()", WRAP_MFN(T, test), asCALL_GENERIC); assert(r >= 0) 
r = engine->RegisterObjectMethod(type, "int selectAxis(int axisId)", WRAP_MFN(T, selectAxis), asCALL_GENERIC); assert(r >= 0);
. . .}
 
template <class T>
void RegisterDerivedMethods(asIScriptEngine* engine, const char* type)
{
    int r;
 
    // Register the inherited Methods by calling
    // the registration of the base Methods
    RegisterBaseMethods<T>(engine, type);
 
    // Now register the new Methods
    // arm64 native calling convention not supported ... using generic
    r = engine->RegisterObjectMethod(type, "int setRPM(int rpm, int acceleration=0)", WRAP_MFN(T, setRPM), asCALL_GENERIC); assert(r >= 0);
    r = engine->RegisterObjectMethod(type, "int getRPM()", WRAP_MFN(T, getRPM), asCALL_GENERIC); assert(r >= 0);
}  

Your problem is that you have registered the setRPM method with signature “int setRPM(int, int)” but the C++ function has the signature “MotorStatus DerivedClass::setRPM(double, double, short, short)”.

You probably have multiple overloads of the setRPM, so you need to use the macro WRAP_MFN_PR to explicitly pick the one you want.

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

DOH!! Sometimes you just get too close to the code and read right through something so obvious.

On a related note, I think I'g going to have to change from asOBJ_VALUE to asOBJ_REF anyway b/c I need to member methods as delegates in scripts. But that for a later thread …

This topic is closed to new replies.

Advertisement