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

Crash bug + some questions

Started by
7 comments, last by WitchLord 16 years, 9 months ago
Hi, I'm currently evaluating AngelScript, playing around with the tutorial project (the 2.9.1 release). Modifying "script.as" to look like this:

class Pie
{
	void foo()	
	{
		Print( "In Pie::foo\n" );
	}
}

float calc(float a, float b)
{
    Pie@ thing = null;
    thing.foo(); // Null dereference
.
.
.

I get a crash in the VM (in as_context.cpp, line 3208). It, of course, works fine if the Pie@ is initialized to a new instance. Now a couple of questions: Why are variables of basic types not initialized to zero? Also, is it possible to get a full script stack trace of when an exception occurs? I tried iterating through the "GetCallStack*" methods in the asIScriptContext but the call stack size is 0 (according to GetCallstackSize) after asEXECUTION_EXCEPTION is returned. I love the binding system BTW. Overall there's a few language features missing, but could possibly deal without them. Thanks.

- Thomas Cowellwebsite | journal | engine video

Advertisement
I'll look into the bug you encountered. Thanks for the very specific bug report, it should be quite easy to find and fix the problem with that.

I chose not to initialize variables to 0 as there's no reason to do it. Only handles and objects are automatically initialized, handles to null and objects with their default constructor, because it wouldn't be safe without that.

Yes, you can get a full stack trace upon exceptions. You'll have to register the exception callback to do that. This exception callback is called before the stack has been unwound, thus allowing you to examine the stack and the variables.

I'm also examining the possibility of holding off the stack unwinding upon exception until the context is released or prepared for another execution, which would then let you examine the call stack after Execute returns asEXECUTION_EXCEPTION. This is not a high priority issue though, so it might be a while for it to be implemented.

I'm glad you liked the binding system. That's pretty much the reason why I started working on this library in the first place.

Let me know which features you feel are missing so I can add them to my to-do list, or if they're already there maybe I can raise their priority.

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've fixed the crash you reported. If you're interested you can get the fix from the SVN (revision 196).

Thanks

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Hi,
Thanks for the quick turn around on the bug-fix, I'll try it when I get home. Good news on the exception handler. Perhaps you should have a stack trace print out as part of the tutorial project (trying out the debug output is usually one of the first things I do when checking out a scripting system -_^).

I'm still of the opinion that things should be initialised to zero in a scripting language, but it's no biggie. Will the compiler warn you if you try to read an uninitialised variable?

How far off are you on implementing inheritance (as described at http://www.angelcode.com/angelscript/wip.asp)? I can probably work without it for the time being, but it's a definite must in the future.

Other than that, there's a few things that would be nice such as in-language exception handling. Reflection and the ability to store meta-data tags would also be very, very awesome.

One other small thing. I noticed you want to implement C++ style initialiser lists. Would it be possible to be able to do that using inline initialisation of member variables (I find C++ style initialiser lists sort of a hack to get around inherent limitations and is a bit ugly syntax wise)? e.g.

class Foo
{
int bar = 123;
Pie@ blah = something();
}

All in all, I think the major limiting factor for me at the moment is inheritance. I'll probably pursue AS further and try a few more in-depth experiments.

Thanks :).

- Thomas Cowellwebsite | journal | engine video

I definitely need to expand the samples and documentation to provide a better showcase for what the library can do.

Yes, the compiler should warn about use of uninitialized variables.

I agree that inheritance is an important feature for the future, but right now I'm concentrating on implementing things that cannot be solved in other ways. Inheritance, although useful, is not absolutely necessary when solving programming problems. AngelScript already has interfaces that can be used for polymorphing so the only thing inheritance would add is code reuse.

By the way, there are many levels of inheritance. Which ones do you feel are the most important?
- single inheritance for registered types
- multi inheritance for registered types (Not sure I can use this)
- single inheritance for script classes
- multi inheritance for script classes (I don't think I'll implement this)
- script classes inheriting from registered types (this one is tricky, but I'd like to give it a try)

Exception handling within the script is probably something that will be implemented soon (and before inheritance).

Could you elaborate on 'reflection' and 'storing meta-data tags'? I'm not sure what this means. If possible, give me an example of their uses.

I'm not a big fan of C++ initializer lists either, but they have one advantage over inline initializations. The order of initializations is completely defined, with inline initializations the order may not be obvious. One thing I'd like to permit in AngelScript is calling another constructor from within the constructor. That way you can reuse code from one constructor in another in a better way. I'll add your suggestion to the to-do list for analysis, perhaps I'll allow that too.

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 would have thought that the order of initialization would be the same as the order the members are defined within the class definition block (just as in C++). As long as you allow any expression to initialize the member inline (i.e. so you can call a custom constructor or refer to another member variable), using C++ style initializer lists won't give you anything over inline initialization.

Inheritance is important to me as far as an entity hierarchy goes. I'm only interested in single inheritance, most importantly single inheritance from one script class to another. Being able to inherit from a C++ type would be very cool, although this would be rather tricky to implement cleanly. Multiple inheritance doesn't really interest me much for what I want to do.

Good news on in-language exception handling. :)

Reflection is the ability to inspect the code dynamically at runtime. For example, it'd be nice if I could have my editor auto-magically find all script classes that derive from type Entity, and have it fill in the entity picker list from that. The code generation aspect of reflection (as in C#) doesn't interest me that much. Wikipedia can probably explain it better than I: http://en.wikipedia.org/wiki/Reflection_%28computer_science%29.

Meta-data would let you attach extra bits of information to any arbitrary symbol. C# attributes are the best example of this. This would allow fun things like attach stuff like "this class should be networked" and "this variable should be serialized on game save".

Here's an overview of C#'s reflection and attributes: http://www.oreilly.com/catalog/progcsharp/chapter/ch18.html

BTW - is it possible for me to pass a handle to a script defined class into C++ (e.g. as a ASObject* of some kind), and call arbitrary methods on that class from C++?

class Thing {    void OnKeyPress(int keycode){}}// This would be called from C++, and C++ would store the script object, // calling "OnKeyPress", etc when engine events come in.Thing@ getTheThing() { return Thing(); }


Thanks again.

- Thomas Cowellwebsite | journal | engine video

The order of the class members in C++ is not guaranteed to be the same as declared in the code (though I haven't seen any case where it actually is different). If I'm going to implement inline initializations I'd like to be able to have member variables initializations depend on each other, e.g:

class MyClass{  int a = b*2;  int b = something();}


I do like the idea of inline initializations, you don't have to convince me of that. I just need to try to think of all the complications before I set out on implementing it. I don't want to start implementing something unless I'm sure it will actually work as I expect, because if it doesn't then I'll be forced to remove the feature again.

What are you trying to establish with a class hierarchy that you cannot do through interfaces? Interfaces obviously would be a work around, until true inheritance is implemented, but you should be able to do pretty much the same thing with them.

// Single inheritanceclass Object  class Shape    class CircleCircle c;Object @o = @c;// Interfaceinterface Objectinterface Shapeclass Circle : Object, ShapeCircle c;Object @o = @c;


The only thing you don't get with the interfaces are the member variables, but you can call a method on an Object handle and be sure it will do the right thing, even if the handle truly is a Circle.

Note, that I'm not trying to convince you that interfaces is just as good as inheritance, because it's not. I'm just trying to show you that until inheritance is supported in AngelScript, you should be able to make do with what is already there. I don't want to loose a new user of AngelScript, just because the library doesn't yet have the requested features. ;)

On the subject of Reflection, yes, of course AngelScript will support that. In some ways it already does, but support for that will improve over time. One of the top things on my to-do list is the support for function pointers, which in my opinion is one of the major missing features in the language right now. I also have plans to allow scripts to modify functions at run-time, i.e. a script may request the compilation of a new function that will replace an already existing function. Of course, the application will have to permit this, the library won't give that ability to the scripts automatically, but it shall be possible to do.

Meta-data might be interesting to support as well. I'll think about how to implement that.

Yes, you can pass script objects to the application, and have the application call methods on it. For your example it would be done something like this:

int funcId = engine->GetFunctionIdByName(0, "getTheThing");asIScriptContext *ctx = engine->CreateContext();ctx->Prepare(funcId);ctx->Execute();asIScriptStruct *obj = *(asIScriptStruct**)ctx->GetReturnPointer();obj->AddRef(); int typeId = obj->GetStructTypeId();funcId = engine->GetMethodIdByName(typeId, "OnKeyPress");ctx->Prepare(funcId);ctx->SetObject(obj);*(int*)ctx->GetArgPointer(0) = keyCode;ctx->Execute();ctx->Release();obj->Release();


Disclaimer: I'm writing this from memory, so it may not actually compile. ;)

Regards,
Andreas

[Edited by - WitchLord on September 11, 2007 12:24:31 PM]

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 pretty sure that the C++ standard specifies that its dependant on the order they appear in the declaration (GCC will actually warn if the order of the initializer list is different than the declaration). For some reason this seems to be an obscure thing to find. It's mentioned in passing at http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.7 in the context of compiler independent language rules : "data members defined in the class are initialized in the order in which they appear in the class declaration".

It's also mentioned here: http://msdn.microsoft.com/msdnmag/issues/0400/c/ and here: http://www.acm.org/crossroads/xrds1-4/ovp.html

It's a real pity the C++ standard itself isn't freely available. :/

As far as your example goes, you would simply have to ensure that b is declared first or you will get undefined results (possibly could have a compiler warning).

class MyClass
{
int b = something();
int a = b*2;
}


The pseudo-inheritance using thing using interfaces is probably a decent work-around for me at the moment. I'm not quite at the stage where I need full-blown entities anyway.

As far as function pointers are concerned, the main reason I use them in other scripting languages (e.g. Python) is to setup callbacks for things like waiting for an animation to finish playing. Being able to use latent methods instead removes the need for alot of callbacks. I'm not saying that they're not neccesarry, just that I probably won't need them for the time being :). Do you plan on making pointers to class members possible?

Good news on the asIScriptStruct interface :>.

- Thomas Cowellwebsite | journal | engine video

It may be useful to allow initialization of member variables in a different order than they are declared. The two doesn't necessarily go hand in hand, one is the data structure representation and the other is the logic.

For now I've added this subject to the to-do list, when I get closer to implementing this I'll decide on the exact way of doing it.

Yes, function pointers would mostly be used for callbacks. But can also be used for Reflection. One interesting example would be:

// AngelScriptvoid main(){   typedef void (*)() func_ptr;   // Compile a function dynamically defined by the script   func_ptr func = Compile("""       void func()       {          print("I'm dynamically compiled");       }       """);   // Let's call our new function   func();}


The above example obviously won't work today. But I intend to support it in the future.

Pointers to class methods probably won't be supported, I don't really see a reason for it. But if someone can give me a convincing argument for it I may consider implementing it.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement