Archived

This topic is now archived and is closed to further replies.

WitchLord

AngelScript 1.8.0 WIP #2 (2004/06/26)

Recommended Posts

WitchLord    4677
Hi guys, I've just released the first work-in-progress version of 1.8.0. You can find it and the description of its changes here: http://www.angelcode.com/angelscript/wip.asp Regards, Andreas Jönsson Author of AngelScript __________________________________________________________ www.AngelCode.com - game development and more... AngelScript - free scripting library - Tower - free puzzle game <SPAN CLASS=editedby>[edited by - WitchLord on June 11, 2004 5:39:04 PM]</SPAN> [Edited by - WitchLord on June 26, 2004 2:16:32 PM]

Share this post


Link to post
Share on other sites
Malmer    122
Just make sure performance is not taking a hit with the new features. Performance is key to a scripting language used in games.

Share this post


Link to post
Share on other sites
EddHead    140
You can eventually call it Angel C++ :D. Anyway as for the other post the 1.7.1a in .NET (i dont have 2003 ) it asks me for a .rc/.res file during compile, so i guess you should check this out, the only way i could fix it was copy the .rc file and recompile (with version changes). i dont know if this is required, but i guess you should try it in .NET sometime to confirm.

Later

Jayanth.K
Raptor Entertainment Pvt. Ltd.
http://www.raptorentertainment.com

Share this post


Link to post
Share on other sites
WitchLord    4677
Malmer:

I''m not adding anything that should change the performance. It will just be more flexible.

Did you note a difference in performance? Perhaps you are compiling the library in debug mode?

EddHead:

I think the problem is not with .NET but with the project file I was distributing. It was referencing a resource file, but I didn''t include the resource file in the distribution. You ought to be able to just remove the reference to the resource file and it should work.

__________________________________________________________
www.AngelCode.com - game development and more...
AngelScript - free scripting library - Tower - free puzzle game

Share this post


Link to post
Share on other sites
EddHead    140
Just make sure teh reference is not present in 1.8.0. just to avoid confusion.

Jayanth.K
Raptor Entertainment Pvt. Ltd.
http://www.raptorentertainment.com

---------------------------------------------------------
The blue pill was a placebo!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
problem using the WIP... Everything links fine and everything, but I get this error when creating the scripting engine (I based everything I did off the sample program):

Failed to create script engine - Expecting library version 1.6.1, found 1.8.0 WIP 20040611

I compiled and linked to the WIP lib. I then included the WIP angelscript.h header. I don't think I am mixing the two versions. Any help?

Share this post


Link to post
Share on other sites
WitchLord    4677
I think you just need to recompile the application. First clean target files to make sure the compiler really compiles all of the modules.

You said you updated the angelscript.h file, but your application is still expecting version 1.6.1. This tells me that the application wasn't compiled with the new angelscript header.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Problem with registering global functions...

the functions are defined like so:
void GetAndReleaseKey(int key);
void GetKey(int key);
void ReleaseKey(int key);

then I try to register them:
r = engine->RegisterGlobalFunction("void GetAndReleaseKey(int)", asFUNCTION(GetAndReleaseKey), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalFunction("void GetKey(int)", asFUNCTION(GetKey), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterGlobalFunction("void ReleaseKey(int)", asFUNCTION(ReleaseKey), asCALL_CDECL); assert( r >= 0 );

and I get this error message:
....
Debug Error:
....
file: "i386\chkesp.c"
Line 42
The value of ESP was not saved properly accross a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with another calling convention.

So, anyone know what's wrong?

Here is how I set up my engine and everything:
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if( engine == 0 ) { hge->System_Log("Failed to create script engine"); hge->System_Log("- Expecting library version %s, found %s", ANGELSCRIPT_VERSION_STRING, asGetLibraryVersion()); return -1; }




Share this post


Link to post
Share on other sites
WitchLord    4677
Do you get the error message when you try to register the functions, or when your script is calling the registered functions?

If it is when you register the functions then something is seriously wrong. It might even be a bug in AngelScript.

If it is when your script is calling the function then perhaps your functions aren't really using the cdecl calling convention. Try declaring the functions with the __cdecl modifier, or if that doesn't work with extern "C".

If you compile the test frame work (available from the WIP page) do you get the same errors?



Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I compiled the test framework and it just comes up with press any key to quit. The error occurs when I try to register the function, not call it. Tell me, what steps do I need to take before I can start registering functions?

Share this post


Link to post
Share on other sites
WitchLord    4677
Since the test framework passed all the tests without any errors at least I know the library is working ok.

The only thing you should have to do before registering functions is to create the engine. Take a look at the source code for the test framework for individual examples showing how to register functions.

I'm thinking that you are having a linkage problem. Somehow your application is not using the same interface or calling convention that the library is. Are you the same Anonymous Poster that was previously using version 1.6.1?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
yes. I guess I will just erase everything angelcode and install it again. I'll let you know what happens.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Yep, I accidentally was mixing the different versions. But, now I have another error (and only one version of angelscript). When I try to register a classes' methods, I get
assertion errors. The registering of stuff is in a different source file, but includes a global header containing the various class definitions.

the registering:

r = engine->RegisterObjectMethod("CGame", "int AddFont(char *filename)", asMETHOD(CGame::AddFont), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CGame", "int AddAnim(char *filename, int frames, int width, int height)", asMETHOD(CGame::AddAnim), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("CGame", "int AddSound(char *filename)", asMETHOD(CGame::AddSound), asCALL_THISCALL); assert( r >= 0 );

Share this post


Link to post
Share on other sites
WitchLord    4677
What WIP version are you using?

With the latest you should take the method pointer with asMETHOD(classname, methodname).

What is the value of r that you receive? Check the value and compare with error codes in angelscript.h.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I downloaded the latest WIP from
[url]http://www.angelcode.com/angelscript/files/angelscript_sdk_180WIP_20040626.zip [/url]

Either I downloaded the wrong WIP, or you forgot to update the zip file.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Oh, I guess I'm using the right one. The error code is -11 or asINVALID_TYPE.

here is how I register the function:
r = engine->RegisterObjectMethod("CGame", "int AddFont(char *filename)", asMETHOD(CGame, AddFont), asCALL_THISCALL); assert( r >= 0 );

Does the class I'm referencing need to be an actual class or an object?


Share this post


Link to post
Share on other sites
WitchLord    4677
Since you get asINVALID_TYPE I assume that you haven't registered the CGame object type.

engine->RegisterObjectType("CGame", sizeof(CGame), flags);

or

engine->RegisterObjectType("CGame", 0, 0);

The second variant prevents the script from instantiating variables of that type, effectively forcing the script to use CGame objects provided by the application either through a global variable or a function.

If you choose the first variant you should read the reference about what the last parameter should be (flags).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I'm sorry that I'm retarded but I can't get this to work. You were right I forgot to uncomment the line registering the CGame type. Now, I get error 10 (asINVALID_DECLARATION). Here is how it happens:

r = engine->RegisterObjectType ("CGame", 0, 0); hge->System_Log("%d", r); assert( r >= 0 );
r = engine->RegisterObjectMethod("CGame", "int AddSound(char*)", asMETHOD(CGame, AddSound), asCALL_THISCALL|asCALL_RETURNBYVAL); hge->System_Log("%d", r); assert( r >= 0 );

Share this post


Link to post
Share on other sites
WitchLord    4677
No worries :)

This time your problem is that you are trying to declare the method parameter as "char*", which isn't recognized by AngelScript. You could however use either one of int8, uint8, or bits8.

I suspect that you wish to be able to send a string to this function, in which case you will have to register a string factory function. If you don't register the string factory, AngelScript won't let you use the string constants. Take a look at the code for registering the bstr for more info on how to do that. You can even use that code directly in your application.

Register bstr source

If you decide to use the bstr code as it is, you'll have to remember to release the bstr that you receive. Or you could change your method to accept a reference to a bstr, as the script engine will be responsible for releasing the memory. I suggest you do the following:


#include "bstr.h"



RegisterBStr(engine);

engine->RegisterObjectMethod("CGame", "int AddSound(const bstr &)", asMETHOD(CGame, AddSound), asCALL_THISCALL);


Where the AddSound method looks like this:


int CGame::AddSound(const asBStr *_str) // Or char **
{
// Dereference the parameter. By receiving the string by
// reference we don't have to deallocate the memory.
char *str = *_str;

// Continue working with str just as you would normally do
...
}


Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
very cool. I also found something called ac_string.

How would I register char* object properties using bstr?

class foo { public: char *bar; };

how would I register bar? Would I just make it a bstr and register like this:

engine->RegisterObjectProperty("foo", "bstr bar", offsetof(foo, bar));

Or, would I just make bar a bstr in both my game and the scripting engine?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Since bstr relies on some extra information than a normal C string has, you'll have to make your "char *bar" a bstr in the game as well.

It is ok to convert a bstr to char * with a static cast for reading purposes, and even updates within the string. But it is not ok to convert a char * to bstr with a static cast, to do that conversion you should allocate memory for the bstr and then copy the string to it.

A bstr has a hidden property that gives the length of the string. The functions registered for bstr uses this hidden property to copy string data, etc.

I recognize that strings are somewhat complicated matter to deal with, but I have yet to find a better solution. The real problem lies in that the script writer shouldn't have to worry about memory leaks when using strings. This unfortunately requires a little more work by the application writer. At least with version 1.8.0 users are free to change the way strings are handled if they don't like the way bstr works.

[edit: I forgot to login]

[Edited by - WitchLord on June 29, 2004 12:52:36 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Nice, I got that working, but have some questions...

When I want to make a string in my host app that will hold script filenames, but using BSTR's, would I use asBSTR *file or
asBSTR file? Could I just say file = new(BSTR)?

Also, let's say I have an object "game" from the class CGame. Do I register everything from the class "CGame" that I want the engine to be able to use, and then register a pointer to the object "game" so that the engine can actually change info in the object? Hmm..That was confusing.

btw:
I think angelcode is a very cool scripting language. I tried out Lua, but it is pretty useless unless you can bind stuff to the scripting engine. Then I tried to compile LuaBind forever, but never had any luck. I'm glad you developed angelscript so you could just open a project and build it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Though I posted right before here, I came up with some more questions:

I am also confused about how to write scripts.

Do I make a "main" function in the script, and that will be the entry point?

I also am wondering how fast the engine compiles scripts. Should I pre-compile all the scripts when the games starts, and then only execute scripts when the time comes, or is that impossible? In larger games with a lot of scripts, I would assume that to be too demanding on memory. But, let's say I want to run the same script several times per frame in my game, I shouldn't recomplile each time, correct? So how can I load a script, compile it, and store it in a buffer or something, and then execute the buffer?

how do scripts execute...Why would I ever suspend the execution of a scripts?

I found this code in one of the example programs. Should I use these functions to load and execute scripts?

int LoadScript(const char *filename)
{
FILE *f = fopen(filename, "rb");
if( f == 0 )
{
hge->System_Log("Failed to open the script file.");
return -1;
}
int len = _filelength(_fileno(f));
acCString code;
code.Allocate(len, false);
int c = fread(code.AddressOf(), len, 1, f);
fclose(f);
if( c == 0 )
{
hge->System_Log("Failed to load script file.");
return -1;
}
int r = engine->AddScriptSection(filename, code, len);
if( r System_Log("An error occured while adding the script section.");
return r;
}
return 0;
}

void AS_CALL COutStream::Write(const char *text) { printf(text); }

int CompileScript()
{
COutStream out;
int r = engine->Build(&out);
if( r System_Log("Failed to compile script."); return -1; }
// If we wish to build again, the script sections has to be added again.
// Now we will verify the interface of the script functions we wish to call
acCString str;
str.Allocate(256, false);
r = engine->GetFunctionDeclaration(engine->GetFunctionIDByName("main"), str.AddressOf(), 256);
if( r System_Log("Failed to retrieve declaration of function 'main'"); return -1; }
if( str != "float main(float, float, float)" ) { hge->System_Log("Function main should be declared as follows 'float main(float, float, float)"); return -1; }
return 0;
}

int ExecuteScript()
{
// Create a context in which the script will be executed.
// Several contexts may exist in parallel, holding the execution
// of various scripts in the same engine. At the moment contexts are not
// thread safe though so you should make sure that only one executes
// at a time. An execution can be suspended to allow another
// context to execute.
asIScriptContext *ctx;
int r = engine->CreateContext(&ctx);
if( r System_Log("Failed to create a context"); return -1; }
// Prepare the context for execution
// When a context has finished executing the context can be reused by calling
// PrepareContext on it again. If the same stack size is used as the last time
// there will not be any new allocation thus saving some time.
r = ctx->Prepare(engine->GetFunctionIDByName("main"), 1000);
if( r System_Log("Failed to prepare context"); return -1; }
// If the script function takes any parameters we need to
// copy them to the context's stack by using SetArguments()
float a = 1.0f, b = 2.0f, c = 3.0f;
r = ctx->SetArguments(0, (asDWORD*)&a, 1);
r = ctx->SetArguments(1, (asDWORD*)&b, 1);
r = ctx->SetArguments(2, (asDWORD*)&c, 1);
// Execute script
hge->System_Log("Starting script execution");
r = ctx->Execute();
if( r System_Log("Unexpected error during script execution"); return -1; }
if( r == asEXECUTION_FINISHED )
{
hge->System_Log("Execution finished successfully\n");
// If the script function is returning any
// data we can get it with GetReturnValue()
float retVal;
r = ctx->GetReturnValue((asDWORD*)&retVal, 1);
hge->System_Log("Returned: %f", retVal);
}
else if( r == asEXECUTION_SUSPENDED )
{
hge->System_Log("Execution was suspended.");
// In this case we can call Execute again to continue
// execution where it last stopped.
acCString str;
str.Allocate(256, false);
int funcID = ctx->GetCurrentFunction();
engine->GetFunctionName(funcID, str.AddressOf(), 256);
hge->System_Log("func : %s", str.AddressOf());
hge->System_Log("line : %d", ctx->GetCurrentLineNumber());
}
else if( r == asEXECUTION_ABORTED )
{
hge->System_Log("Execution was aborted.");
}
else if( r == asEXECUTION_EXCEPTION )
{
hge->System_Log("An exception occured during execution");
// Print exception description
acCString str;
str.Allocate(256, false);
int funcID = ctx->GetExceptionFunction();
engine->GetFunctionName(funcID, str.AddressOf(), 256);
hge->System_Log("func : %s", str.AddressOf());
hge->System_Log("line : %d", ctx->GetExceptionLineNumber());
ctx->GetExceptionString(str.AddressOf(), 256);
hge->System_Log("desc : %s\n", str.AddressOf());
}
// Don't forget to release the context when you are finished with it
ctx->Release();
return 0;
}

Share this post


Link to post
Share on other sites