Advertisement

binding functions that take/return std::list/std::vector

Started by August 18, 2014 01:56 PM
2 comments, last by sorressean 10 years, 3 months ago

hello all:

I'm setting up scripting, which I will use to add content to my mud. I am running into an issue however: how does one bind a function that either takes or receives std::list or std::vector? Any information here would be really appreciated. I have a method that looks something like:

std::list<Entity*>* Entity::GetContents() { ... }

and am trying to bind it.

Thanks,

To register these methods directly with AngelScript you would first have to register the std::list/vector with the engine for the type you'll return/receive.

stdvector.h from the svn shows the basics of registering the std::vector type with AngelScript.

However, I do not recommend that you register the std::list/vector directly with AngelScript. They are not well suited for the automatic memory management, and you would likely end up with performance bottlenecks due to the memory in the containers being copied whenever the container is being passed around in the script.

Instead I recommend you write a wrapper around your application functions that take/receive std::list/vectors to transform the container into a type that is better suited for automatic memory management (i.e. with refcounting). In most cases the CScriptArray add-on type is good enough, and is the recommended starting point.

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

Advertisement

Here's a helper function I use to get a script array from an application-registered type which returns an std::vector:


engine->RegisterObjectMethod("MyScene", "array<MySprite@>@ FindSprites(const string& in) const", asFUNCTION(FindSprites), asCALL_CDECL_OBJLAST);

CScriptArray* FindSprites(const std::string& name, MyScene* scene)
{
    std::vector<MySprite*> sprites = scene->FindSprites(name);

    asIObjectType* objectType = MyWrapper_GetEngineObjectTypeFromDecl("array<MySprite@>");

    CScriptArray* scriptArray = CScriptArray::Create(objectType, sprites.size());

    for (uint i = 0; i < sprites.size(); ++i)
    {
        void* ptr = sprites[i];
        scriptArray->SetValue(i, &ptr);
    }

    return scriptArray; // don't delete array because script will now have a refcount of 1 to it, and will take care of the memory from here
}

And here's one which lets you give a script array, yet pass that to an application-registered type which expects a vector:


engine->RegisterObjectMethod("MySprite", "void SetOffsets(const array<MyVec2> &in)",  asFUNCTION(SetOffsets), asCALL_CDECL_OBJLAST);

void SetOffsets(CScriptArray& offsets, MySprite* sprite)
{
    const uint arraySize = offsets.GetSize();

    std::vector<MyVec2> offsets(arraySize);

    for (uint arrayIdx = 0; arrayIdx < arraySize; ++arrayIdx)
    {
        const MyVec2* pos = static_cast<const MyVec2*>(offsets.At(arrayIdx));

        offsets[arrayIdx].Set( *pos );
    }

    sprite->SetOffsets(offsets);
}

Hello:

Thanks a lot for the help, really appreciate it. This is a bit messy, but I don't return a lot of std::list objects. thanks again.

This topic is closed to new replies.

Advertisement