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

Binding a member function that returns a vector of pointers

Started by
3 comments, last by Starfox 11 years ago

I have a class object with this member function:

[source]

template<class T>

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

{

...

}

[/source]

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

[source]

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);
}

[/source]

Next I declare this helper function for AngelScript binding purposes:

[source]

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);
}
// The ref count for the returned handle was already set in the array's constructor
return arr;
}
return 0;
}

[/source]

Next, I bind my object class as such:

[source]

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);
}

[/source]

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/
Advertisement

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

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

[source]

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

[/source]

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/

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

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

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

This topic is closed to new replies.

Advertisement