• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
SiddharthBhat

Returning an Interface type

7 posts in this topic

Hi all!

 

I've been writing a class called "actorList", which is basically a list of all actors. I'm not using the array type because I want to extend this type to support some additional features like filtering, ordering, etc.

 

"Actor" is an interface. there are different types of actors in my game, such as componentActor, Light and Sound. ALL of the derived classes of Actor have turned off garbage collection (I distrust the garbage collector >_>. The script side only has restricted entry points and is not allowed to instantiate these classes. Hence, I decided to turn garbage collection off.)

 

 

 

class actorList{
public:
    int getSize(){
        return this->actors.size();
    };
    Actor *get(int index){
        return this->actors[index];
    };


    void  Add(Actor *a){
        this->actors.push_back(a);
    }


    void Clear(){
        this->actors.clear();
    }


    actorList(std::vector<Actor *>actors){
        this->actors = actors;
    }


    actorList(const actorList &other){
        this->actors = other.actors;
    }


    actorList(){};
    ~actorList(){};


private:
    std::vector<Actor *>actors;
};
 

I've been trying to bind " Actor *get(int index)" and I'm not able to do it :/ 

 

 

--------------------------------------------------------------------------------------------------------------------------------------------------

I've been binding the function this way:

 

 

 

//function is Actor *get(int index)
actorListDef.addMethod(AS_ObjMethodDef("Actor@ Get(int index)", 
        AS_FunctionDef(asMETHODPR(actorList, get, (int index), Actor*), asCALL_THISCALL )));
 

 

 

If I access it from the script side like so:

 

 

Actor @actor;

//this statement makes sense right? *p = *q;
@actor = @allActors.Get(i);
 
 

 

 

or like so:

 
 
Actor @actor;

//*p = q I don't know what this means 
@actor = allActors.Get(i);
 

 

 

      It goes and crashes at as_engine.cpp at line number 3333. These are the surrounding lines:

void asCScriptEngine::CallObjectMethod(void *obj, int func)
{
    asCScriptFunction *s = scriptFunctions[func]; <-- this is where it crashes
    asASSERT( s != 0 );
    CallObjectMethod(obj, s->sysFuncIntf, s);
}
 

 Here, the  "this" appears to have been freed and has been set to Visual Studio's "memory freed" debug pattern - 0xfeeefeee

 

 

 

- this    0xfeeefeee {isPrepared=??? memoryMgr={cs={cs={DebugInfo=??? LockCount=??? RecursionCount=??? ...} } ...} ...}    asCScriptEngine *
 

 

 

//------------------------------------------------------------------------------------------------------------------------------------------

I also tried binding it this way:

 

 

void get(int index, Actor **a){
        *a = this->actors[index];
    }
 

 Here's how I bound it to the script side:

 

 

actorListDef.addMethod(AS_ObjMethodDef("void Get(int index, Actor &out)", 
        AS_FunctionDef(asMETHODPR(actorList, get, (int index, Actor **a), void), asCALL_THISCALL )));
 

because the documentation said this:



&out : A reference to an unitialized value is passed to the function. When the function returns the value is copied to the true reference. The argument expression is evaluated only after the function call. This is the best way to have functions return multiple values.

 

 

 

But on doing this, it says "No default constructor for object of type 'Actor'. " as well as "There is no copy operator for the type 'Actor' available." , and then the usual unable to Prepare, unable to Exexute.

 

 

Help, Anyone? sad.png I have no clue as to what I'm doing wrong / what I'm supposed to do. 

Thanks

~Bollu

 
Edited by bollµ
0

Share this post


Link to post
Share on other sites

Bump?

 

if no one knows what to do, could I at least have some pointers as to what I maybe doing wrong and / or propose a change to the architecture? Thanks.

0

Share this post


Link to post
Share on other sites

@a = @b; means a handle assignment, i.e. handle a will point to the same object as handle b

@a = b; same thing, the compiler knows you want to do a handle assignment because of the left-hand @ and thus implicitly takes the handle of the right-hand expression

a = b; means a value assignment, i.e. the content of b will be copied to the content of a

 

 

In your first attempt, i.e. when get returned an Actor*. You forgot to increase the reference counter before returning the pointer. AngelScript will call Release() on the pointer it receives, so you must call AddRef() or else the object will be freed too early. Alternatively you can tell AngelScript to automatically increase the reference count by registering the method like this:

 

 

//function is Actor *get(int index)
actorListDef.addMethod(AS_ObjMethodDef("Actor@+ Get(int index)", 
        AS_FunctionDef(asMETHODPR(actorList, get, (int index), Actor*), asCALL_THISCALL )));

 

Observe the + sign after the @ symbol. This is called auto handles in the manual.

 

 

In your second attempt that returns the Actor as an output parameter, you registered the method incorrectly. It should have been registered as:

 

 

actorListDef.addMethod(AS_ObjMethodDef("void Get(int index, Actor @ &out)", 
        AS_FunctionDef(asMETHODPR(actorList, get, (int index, Actor **a), void), asCALL_THISCALL )));

 

The Actor @&out in AngelScript matches Actor ** in C++. Observe that here too you need to increase the reference count, or use auto handles to have AngelScript do it.

 

You had registered it as 'Actor &out', which matches 'Actor &' in C++, i.e. a reference to an existing instance is passed to the function to be updated with the return value. This is why you got the error 'No default constructor' when AngelScript tried to create the instance you told it to pass to the function.

 

 

Here's a few articles from the manual that may help clarify these subjects:

 

Regards,

Andreas

Edited by Andreas Jonsson
1

Share this post


Link to post
Share on other sites

Ah! that makes perfect sense biggrin.png. Thank you! I used the second method and It's perfectly fine now.

 

But I have a question: I've disabled garbage collection on these objects (Actor is an interface, so I'm not sure how to disable the GC on that) by adding the flag asOBJ_NOCOUNT while binding the interface. so shouldn't the 1st method work independent of whether I call AddRef or not? I mean, isn't the GC not supposed to clear objects that have disabled reference counting?

 

Thanks

~Bollu

 

EDIT: It's not fine, it's not crashing, but it's still returning a null pointer. I used the Angelscript debugger. The memory location of Actor @actor is still NULL (0x00...). So it's not getting copied properly. 

 

The C++ side function:

 

void get(int index, Actor **a){
        *a = this->actors[index];
    }

 

Binding:

 

 

actorListDef.addMethod(AS_ObjMethodDef("void Get(int index, Actor @ &out)", 
        AS_FunctionDef(asMETHODPR(actorList, get, (int index, Actor **a), void), asCALL_THISCALL )));
 

 

script-side:

 

 

 

Actor @a;
actorList allActors = getAllActors();

allActors.Get(0, @a);
 

 

And yes, a valid pointer exists inside the actorList class. I put a breakpoint to check. everything is fine and all the pointers are present. The pointer to pointer even gets equated to the right memory address. but after returning from the Get function call, in the next statement, (I know this because I was stepping using angelscript's debugger), it's back to NULL.

 

I have no idea >.<; help, please?

 

 

 

Edited by bollµ
0

Share this post


Link to post
Share on other sites

I'm sorry. I missunderstood what you meant by disabling garbage collection. When you said that I though you simply didn't register the garbage collector behaviours or even turned off the automatic execution of the garbage collector, not that you registered the object types with asOBJ_NOCOUNT to skip the reference counting.

 

To me garbage collecting and reference counting are two different things. :)

 

Anyway, if you register the types with asOBJ_NOCOUNT then AngelScript won't call the AddRef or Release behaviours. It won't allow you to use autohandles either for these types. 

 

 

Still, you say you disabled garbage collector on all types, except Actor. What do you mean? How exactly have you registered the Actor type? Is it not registered with asOBJ_NOCOUNT as well?

0

Share this post


Link to post
Share on other sites

My bad :) you're right, I've disabled reference counting.

 

"Actor" is an interface, it's not an object per se. I was of the opinion that one cannot register behaviours to interfaces.  

 

using this function:

 

 

asIScriptEngine::RegisterInterface(const char * name)
 

I didn't see a parameter to pass the flags like you can to RegisterObjectType. So, I didn't do anything. just used registerInterface with Actor, and a few trivial functions (getName, getPosition) and the like.

 

All of the concrete derived classes of Actor (which are all reference types) have been registered with the asOBJ_NOCOUNT flag.

 

thanks

~Bollu

0

Share this post


Link to post
Share on other sites

Ah. There is the error. smile.png

 

RegisterInterface() is meant to allow you to register script interface declaration that the application needs to know of. This is not meant to be used for C++ interfaces.

 

When you return the Actor handle, AngelScript believes you're returning a asCScriptObject *, i.e. a script class, not a C++ class. Exactly what will happen in this case is unknown, but it is certain that you'll end up with unexpected results as you noticed. :)

 

You need to register your C++ Actor interface just like an ordinary C++ type, i.e. with RegisterObjectType("Actor", 0, asOBJ_REF | asOBJ_NOCOUNT);

1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0