Advertisement

How to tell if a function parameter is an object?

Started by April 30, 2014 05:12 PM
1 comment, last by metsfan 10 years, 6 months ago

Hello all,

First, let me describe the behavior I am trying to implement. I have created a custom wrapper around Angelscript functions in order to make calling them easier. One of my wrapper functions handles the "pointer" case (i.e. the user passes a pointer as a parameter). In this situation, Angelscript can either accept this parameter using SetArgObject or SetArgAddress. What I would like to do is try SetArgObject first, and if that fails, then try SetArgAddress. However, the problem I am facing is that if I pass an invalid parameter to the context, it invalidates the entire context, and prepare must be called again in order to use the context again.

I did some digging into the Angelscript code and noticed that before the context actually sets the argument in SetArgObject, it first checks the function to see that the parameter is an object, and if it's not, it returns and error and sets the error code. It would have been nice, however, to know before calling SetArgObject that the call would be rejected, so that I didn't have to invalidate the context. The problem is it seems the data types used by Angelscript to check if the parameter is an object are hidden from the front-facing API.

What I would ideally like is to do the same check that the context does before setting the object to make sure I am passing in a valid object to the context to avoid destroying the current context state. Does anyone know any way to do this, other than modifying Angelscript?

I hope this hasn't been too hard to follow.

P.S. For Andreas: one solution I have come up with is to expose the asCDataType as asIDataType and allow users to query the data types for function parameters in the public asIScriptFunction interface. I would create a new method on asIScriptFunction, like GetDataTypeForVar(int index) which would return an asIDataType. If you are happy with this solution, I can implement it and send you a patch for your approval.

I do something similar. Here's a snippet of what I do (in debug-only):


for (unsigned int i = 0; i < params.size(); ++i)
{
    int funcParamTypeId = asINVALID_ARG;
    const int funcGetParamRet = func->GetParam(i, &funcParamTypeId);
    assert( funcGetParamRet == asSUCCESS && funcParamTypeId != asINVALID_ARG );

    if ( (funcParamTypeId & asTYPEID_SCRIPTOBJECT) )
    {
        // function is expecting a primitive or application-registered object, but is getting a script object??
        return false;
    }
    else if ( (funcParamTypeId & asTYPEID_MASK_OBJECT) )
    {
        asIObjectType& funcParamObjType = derefOrAssertIfNull(scriptEngine.GetObjectTypeById(funcParamTypeId));

        // check that type matches our known application-registered value/reference types
        // ...
    }
    else if ( funcParamTypeId >= asTYPEID_BOOL && funcParamTypeId <= asTYPEID_DOUBLE )
    {
        // function is expecting a primitive. check that that's what's being given for this param
        // ...
    }
    else
    {
        // unexpected typeId. something went wrong (?)
    }
}

Maybe this thread will help you choose to call just one or the other: "SetArgAddress can be used for both references and handles. For handles it will not automatically increment the object reference. SetArgObject can be used for handles, references to objects, and objects sent by value. For handles it will automatically increment the reference, and for objects sent by value it will make a copy of the object. Usually you'll want to use SetArgAddress for references, and SetArgObject for handles and objects sent by value."

Advertisement

I do something similar. Here's a snippet of what I do (in debug-only):

Maybe this thread will help you choose to call just one or the other: "SetArgAddress can be used for both references and handles. For handles it will not automatically increment the object reference. SetArgObject can be used for handles, references to objects, and objects sent by value. For handles it will automatically increment the reference, and for objects sent by value it will make a copy of the object. Usually you'll want to use SetArgAddress for references, and SetArgObject for handles and objects sent by value."

I did see that quote, but I do want the behaviors of SetArgObject to be used if at all possible. I will give your solution a try. I inspected the code to get a variable's type ID, and I don't like how much code is executed just to get a value that is already cached in the asCScriptFunction object, which is why I was hoping there was another way, but this seems like it would work out fine Thank you.

This topic is closed to new replies.

Advertisement