Advertisement

Returning arrays of ""pointers""?

Started by August 08, 2018 01:49 AM
6 comments, last by Servant of the Lord 6 years, 3 months ago

I'm new to Angelscript.

I have some classes that I don't want scripts to create, but that I want to give scripts access to. I have several different class types like that ("Player","Enemy","Event", - scripts should never create any of these).

Would the appropriate registration flags be asOBJ_REF and asOBJ_NOCOUNT, and then simply not registering the constructors/destructors? All of these are guaranteed to out-live the scripts.


engine->RegisterObjectType("Event", sizeof(EventStructure_Server), asOBJ_REF | asOBJ_NOCOUNT)

 

I want (C++-side) functions that returns arrays of these references/pointers.

Things like, "event.GetPlayersInRange(pos, range)"

I see there is a CScriptArray, but I don't understand if this is a *replacement* for an existing built-in array type, or if there is no default array type?

In C++, how would I create an array of non-reference-counted references to return?

Is this correct: (going off of the addon Array example)


// Registered with AngelScript as 'array<Enemy> @CreateArrayOfString()'
CScriptArray *GetEnemiesInRange(cPointF pos, float radius)
{
    asIScriptContext *ctx = asGetActiveContext();
    Assert(ctx, "Error! Can only call this function from within scripts");
    
    asIScriptEngine* engine = ctx->GetEngine();
    
                                             //  vvv Should this just be "Enemy"?                          
    asITypeInfo *typeInfo = engine->GetTypeInfoByDecl("array<Enemy>");
    
    std::vector<Enemy*> enemies = /*...whatever...*/;
    
    CScriptArray *arr = CScriptArray::Create(typeInfo, enemies.size());
    for( asUINT i = 0; i < arr->GetSize(); i++ )
    {
        arr->SetValue(i, enemies[i]); //Just give the CScriptArray pointers to the Enemy instances?
    }
    
    return arr;
}

 

I think you are doing the right thing.

Just use handles to your classes "array<Enemy@>" instead of "array<Enemy>" maybe?

If you use "Enemy" directly, the script will create a new physical object in that scope.
You can refresh on handles herehttps://www.angelcode.com/angelscript/sdk/docs/manual/doc_script_handle.html

Advertisement

Thank you, that link helped alot. I must've missed the 'handle' stuff, distracted by 'references'.

Quote

Would the appropriate registration flags be asOBJ_REF and asOBJ_NOCOUNT, and then simply not registering the constructors/destructors? All of these are guaranteed to out-live the scripts.

Yes. this is suitable with your assumption that the objects out-live the scripts. 

Quote

I see there is a CScriptArray, but I don't understand if this is a *replacement* for an existing built-in array type, or if there is no default array type?

There is no built-in array type, just as there is no default string type. I've opted for having these implemented externally so each application developer can decide how to do their own types. The add-ons are provided as a default implementation, but can be replaced by custom implementation if so desired.

 

 

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 having some trouble returning the array of pointers. Everything seems fine, and the array ends up the correct size (in my test cases, I'm only putting one element in it), but the pointer in the array on the script-side is null, despite me putting a valid pointer into it, on the C++ side.


CScriptArray *GetTestCharArray()
{
    static Character character;
    character.name = "CharName";

    asIScriptContext *context = asGetActiveContext();
    Assert(context, "Error! Can only call this function from within scripts");
    asIScriptEngine *engine = context->GetEngine();

    asITypeInfo *typeInfo = engine->GetTypeInfoByDecl("array<Character@>");

    CScriptArray *arr = CScriptArray::Create(typeInfo, 1);
    arr->SetValue(0, &character);

    return arr;
}

//Elsewhere, where registering the function:
RegisterScriptArray(engine, true);
asCheck(engine->RegisterObjectType("Character", sizeof(Character), asOBJ_REF | asOBJ_NOCOUNT));
asCheck(engine->RegisterObjectProperty("Character", "string name", asOFFSET(Character, name)));

asCheck(engine->RegisterGlobalFunction("array<Character@> @GetTestCharArray()", asFUNCTION(GetTestCharArray), asCALL_CDECL));

Here's the Angelscript side of things:


void Fireball(Enemy &enemy)
{
	array<Character@> @chars = GetTestCharArray();
	
	//Correctly prints a length of '1'.
	print("Num players: " + formatUInt(chars.length()));
	
	//Prints "null" (but it shouldn't be null...) 
	if(chars[0] is null) print("null");
	else print("not null");
	
	//Script crashes and reports a "Null pointer access"
	print("Character " + formatUInt(0) + ": " + chars[0].name);
}

Is there some obvious mistake I'm making?

[Edit:] I simplified the code even further from what I originally posted, but the array elements are still null.

I believe the problem is that you're not passing the correct value to SetValue.

The array is an array of handles (a.k.a. pointers), so SetValue expects the address to the pointer to the Character object. 


CScriptArray *GetTestCharArray()
{
    static Character character;
    character.name = "CharName";

    asIScriptContext *context = asGetActiveContext();
    Assert(context, "Error! Can only call this function from within scripts");
    asIScriptEngine *engine = context->GetEngine();

    asITypeInfo *typeInfo = engine->GetTypeInfoByDecl("array<Character@>");

    CScriptArray *arr = CScriptArray::Create(typeInfo, 1);
    Character *pointer = &character;
    arr->SetValue(0, &pointer);  // Give the address of the pointer to the object

    return arr;
}

I'm not sure why in your case it looks like it is becomes a null pointer, but I presume it is because the first bytes of your Character object is holding zeroes, which would then be copied as if they were a null pointer.

 

 

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

Thank you, that indeed was the problem.

And thanks for writing Angelscript and making it opensource, it's actually enjoyable integrating into my code - especially what with the native function calling!

This topic is closed to new replies.

Advertisement