Jump to content
  • Advertisement
Sign in to follow this  
Wavesonics

Proper registration for this type?

This topic is 3540 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a type I want to register that I want to be used as such: - I should be able to pass an application instance of it to a script, and I want the script to be able to directly modify the application's instance. - I also don't want the object to be controlled by the scripts GC or reference counting. The life time of the object should be completely controlled by the application, and the script should not hold references to it. Now I've tried to register it as both of these:
r = m_engine->RegisterObjectType("Creep", sizeof(Creep), asOBJ_VALUE | asOBJ_APP_CLASS | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR ); assert( r >= 0 );

r = m_engine->RegisterObjectType("Creep", sizeof(Creep), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS ); assert( r >= 0 );


The first isn't ideal, because I don't really want to be able to construct or destruct these objects in scripts. On this note, if I only have a non-default constructor, how do I pass arguments to it via the method described here:
void Constructor(void *memory)
{
  // Initialize the pre-allocated memory by calling the
  // object constructor with the placement-new operator
  new(memory) Object();
}

void Destructor(void *memory)
{
  // Uninitialize the memory by calling the object destructor
  ((Object*)memory)->~Object();
}

// Register the behaviours
r = engine->RegisterObjectBehaviour("val", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Constructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("val", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );


Anyway, with both of these methods, I manage to run and even compile the script, but when I attempt to use it here, things go bad:
// The Script:
void fire( Creep@ c ) {
    int h = c.health();
	c.health( h - 5 );
	print( "The creeps health is now: " );
	print( c.health() );
	print( "\n" );
}

// The point of call:
asIScriptContext* ctx = gScriptEngine.prepare( description->script, "void fire( Creep@ )" );
ctx->SetArgObject( 0, &c );
gScriptEngine.execute( ctx );


If I'm not mistaken, the @ symbol is what I want for passing things as references right? Now it prints "The creeps health is now: 5" which is perfect, but then I get a random crash in the next few lines of code. It changes what line each time I run. Clearly, the memory for the object has been corrupted. Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
If you don't want the script to be able to instanciate the type, then you should register the type as a reference type without any factory function. All value types must be instanciable by AngelScript.

If you also do not want the script to be able to hold any extra references to the type then you can register the type with the asOBJ_NOHANDLE flag, in which case the ADDREF and RELEASE behaviours shouldn't be registered.

If you want to allow the script to store reference to the type, but don't care about reference counting, then you can register dummy functions for ADDREF and RELEASE that doesn't do anything. In this case the application will be responsible for making sure the instance outlives all references that the script may store (for example global variables).

---

Non-default constructors are implemented as such:


void constructor(int arg, void *memory)
{
new(memory) Object(arg);
}

r = engine->RegisterObjectBehaviour("val", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTIONPR(Constructor, (int, void*), void), asCALL_CDECL_OBJLAST); assert( r >= 0 );


You can also use asCALL_CDECL_OBJFIRST, in which case the memory pointer should be placed as the first argument.

---

The @ symbol (means 'object handle') is only available for reference types.

In fact the script you compiled should have given a compilation error when you declared the parameter as a handle to Creep, since you registered the Creep type as a value type. I'll have to look into why this didn't happen.

EDIT: This was indeed a bug. I've already found and fixed it. The fix should be available in the SVN this weekend.

[Edited by - WitchLord on January 16, 2009 7:25:12 AM]

Share this post


Link to post
Share on other sites
Awesome, this is why I like working with a library that is so actively and personally maintained :)

Ok, I registered it as such:

// Register our Creep
r = m_engine->RegisterObjectType("Creep", sizeof(Creep), asOBJ_REF ); assert( r >= 0 );
r = m_engine->RegisterObjectBehaviour("Creep", asBEHAVE_ADDREF, "void f()", asMETHOD(Creep, dummy), asCALL_THISCALL); assert( r >= 0 );
r = m_engine->RegisterObjectBehaviour("Creep", asBEHAVE_RELEASE, "void f()", asMETHOD(Creep, dummy), asCALL_THISCALL); assert( r >= 0 );



And everything works just fine. Pretty cool to see things happening due to scripts in my game now :)

One little nag though. I like the keep the public interface to my classes concise. So I tried using: asFunction() instead of asMETHOD(), so I could redirect to a dummy global function and keep my class clean. But it throws at the assert().

Would it be possible to support none reference counted objects in a more natural way for future versions? Maybe a flag in the type register that would automatically register dummy functions or something?

Share this post


Link to post
Share on other sites
When you register a non-member function for object behavior, you should register the function as asCALL_CDECL_OBJFIRST or asCALL_CDECL_OBJLAST. This also requires that the function use the cdecl calling convention (rather than, for example, fastcall or stdcall).

Share this post


Link to post
Share on other sites
Quote:
Original post by Wavesonics
One little nag though. I like the keep the public interface to my classes concise. So I tried using: asFunction() instead of asMETHOD(), so I could redirect to a dummy global function and keep my class clean. But it throws at the assert().


Follow SiCrane's advice and you won't have to modify your classes. :)

Quote:
Original post by Wavesonics
Would it be possible to support none reference counted objects in a more natural way for future versions? Maybe a flag in the type register that would automatically register dummy functions or something?


Yes, I have plans to allow this in a future version. It's a low priority though.

Share this post


Link to post
Share on other sites
Great, thanks!

Btw, I'm not clear on the difference between:
cdecl, fastcall, or stdcall.

Though I think stdcall had to do with the MSVC++ compiler?

Share this post


Link to post
Share on other sites
These are different calling conventions. The basic difference is this:

- cdecl: the arguments are pushed on the stack by the caller, and removed by the caller after the callee returns
- stdcall: the arguments are pushed on the stack by the caller, and removed by the callee before it returns
- fastcall: the arguments are placed in the registers


The default calling convention is cdecl, unless you have changed this in the project settings.

stdcall is the standard calling convention used by Microsoft's Platform SDK. Though I believe they originally inherited this calling convention from the Pascal language. stdcall is not exclusive to MSVC++, though it's less commonly used on platforms that aren't Windows based.

fastcall is as the name suggests, a faster calling convention, as there are less memory operations involved with a function call. Though it is rarely used nowadays, as the modern compilers more than enough make up for most human made optimizations.

Share this post


Link to post
Share on other sites
Ah, great, thanks for the info!

I actually may get much deeper into this. I'm currently implementing AngelScript in a small hobby project which I am using to research new libs and techniques.

Most of which I will be implementing in my next project at work. So I may be porting AngelScript's native calling to the Wii when I use it at work.

I already wrote our Font rendering system based around your BMFont format, thanks again for that, it was a breeze!

Share this post


Link to post
Share on other sites
Hi Wavesonics. Have you had any progress with native calling on the Wii? I'm assuming you are using CodeWarrior since you are doing this at work.

Hi Andreas. Long time no speak. It's not a coincidence that two people are asking about CodeWarrior at the same time. CliffCawley is on my team. :)

Share this post


Link to post
Share on other sites
Hi Sly. It has indeed been a while. So CliffCawley is with you? Now I've had the honor of getting in touch with quite a few from Krome Studios, 4 to be exact. :) I'm happy to hear that interest in AngelScript is still high over there.

I have a feeling that Wii support isn't too far away. There has been quite a lot of interest in this lately, and hopefully someone will be able to get this going soon.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!