Jump to content

  • Log In with Google      Sign In   
  • Create Account


- - - - -

Binding a member function that returns a vector of pointers


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 Starfox   Members   -  Reputation: 504

Like
0Likes
Like

Posted 17 June 2013 - 12:51 AM

I have a class object with this member function:

template<class T>
std::vector<T*> object::components_of_type() //returns a vector with pointers to the object's components of type T
{
...
}

 

I want to bind a few helper functions to this member function to AngelScript. First I declare my rigid_body_component type:

 
void bind_rigid_body_component(asIScriptEngine* Engine)
{
    Engine->RegisterObjectType("rigid_body_component", sizeof(rigid_body_component), asOBJ_REF | asOBJ_NOCOUNT);
    //
    Engine->RegisterObjectMethod("rigid_body_component", "void apply_force(const float3&in)", asMETHODPR(rigid_body_component, apply_force, (const float3) , void), asCALL_THISCALL);
}
 

 

Next I declare this helper function for AngelScript binding purposes:

 
CScriptArray* object_rigid_body_components(object* Object)
    {
        // If called from the script, there will always be an active
        // context, which can be used to obtain a pointer to the engine.
        asIScriptContext *ctx = asGetActiveContext();
        if( ctx )
        {
            asIScriptEngine* engine = ctx->GetEngine();
            // The script array needs to know its type to properly handle the elements.
            // Note that the object type should be cached to avoid performance issues
            // if the function is called frequently.
            asIObjectType* t = engine->GetObjectTypeById(engine->GetTypeIdByDecl("array<rigid_body_component@>"));
            // Create an array with the initial size of N elements
            const auto RigidBodyComponents = Object->components_of_type<rigid_body_component>();
            const auto N = RigidBodyComponents.size();
            CScriptArray* arr = new CScriptArray(asUINT(N), t);
            for( asUINT i = 0; i < arr->GetSize(); i++ )
            {
                arr->SetValue(i, RigidBodyComponents[i]);
            }
            // The ref count for the returned handle was already set in the array's constructor
            return arr;
        }
        return 0;
    }
 

 

Next, I bind my object class as such:

 
void bind_object(asIScriptEngine* Engine)
{
    Engine->RegisterObjectType("object", sizeof(object), asOBJ_REF | asOBJ_NOCOUNT);
    //
    Engine->RegisterObjectMethod("object", "array<rigid_body_component@> rigid_body_components()", asFUNCTION(object_rigid_body_components), asCALL_CDECL_OBJLAST);
}
 

 

The last call to RegisterObjectMethod gives me the error output "(0, 0) : ERR  : Failed in call to function 'RegisterObjectMethod' with 'object' and 'array<rigid_body_component@> rigid_body_components()'". What am I doing wrong? I can't find an example for binding a function that returns an array of elements around - if I'm missing one please point me to it.


Holy crap I started a blog - http://unobvious.typepad.com/

Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3293

Like
0Likes
Like

Posted 17 June 2013 - 05:58 PM

The function needs to be registered as returning the array by handle, i.e.

 

Engine->RegisterObjectMethod("object", "array<rigid_body_component@> @rigid_body_components()", asFUNCTION(object_rigid_body_components), asCALL_CDECL_OBJLAST);

 

As for examples, you might check the function StringSplit() in the scriptstdstring add-on, or the method CScriptDictionary::GetKeys() in the scriptdictionary add-on.

 

Regards,

Andreas


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

#3 Starfox   Members   -  Reputation: 504

Like
0Likes
Like

Posted 18 June 2013 - 12:35 AM

I'm not sure whether that worked - I no longer get error output but when I try to execute this code snippet: 

 

 
rigid_body_component@ R = self.rigid_body_components()[0];
R.apply_force(float3(0, 1, 0));

 

apply_force() is called but the 'this' pointer value is incorrect. Am I missing something?


Holy crap I started a blog - http://unobvious.typepad.com/

#4 Andreas Jonsson   Moderators   -  Reputation: 3293

Like
0Likes
Like

Posted 18 June 2013 - 10:29 AM

The problem is with how the array is populated.

 

As the array is holding handles to the rigid_body_components, the SetValue() method should be given a pointer to a pointer to the rigid_body_component. You need to change inner loop in object_rigit_body_components to the following:

 

            for( asUINT i = 0; i < arr->GetSize(); i++ )
            {
                // SetValue expects to receive a pointer to the value. The value in this case is the pointer 
                // to the object, so it is necessary to pass in a pointer to the pointer to the object.
                void *ptr = RigidBodyComponents[i];
                arr->SetValue(i, &ptr);
            }

 

Regards,

Andreas


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

#5 Starfox   Members   -  Reputation: 504

Like
0Likes
Like

Posted 18 June 2013 - 01:57 PM

Aha, got it. It works perfectly now, thanks a million Andreas.


Holy crap I started a blog - http://unobvious.typepad.com/




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS