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

Total beginner exec problems

Started by
7 comments, last by WitchLord 19 years, 2 months ago
I've just downloaded angelscript and have tried to make a simple program based on the sample and the documentation. Here is my code:
#include <iostream>
#include <string>

#pragma comment(lib, "angelscriptd.lib")
#include "angelscript.h"

int i;

void print(char c)
{
	std::cout << "print()" << c << std::endl;
}

int main()
{
	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	if(engine == 0)
	{
		std::cout << "Failed to create script engine\n";
		return -1;
	}

	engine->RegisterGlobalProperty("int i", &i);

	engine->RegisterGlobalFunction("void print(char)", asFUNCTION(print), asCALL_CDECL);

	std::string input;

	for(;;)
	{
		std::cin >> input;
		if(input == "q")
			break;

		int r = engine->ExecuteString(0, input.c_str());
		if(r < 0)
			std::cout << "Invalid script statement.\n";
		else if(r == asEXECUTION_EXCEPTION)
			std::cout << "A script exception was raised.\n";
	}

	engine->Release();


	return 0;
}
As you can see I'm trying to execute whatever is typed into the console. However I always get an "Invalid script statement." error. I've tried typing many things into the console from i = i + 1; to print("d");. Both with and without the semi-colon (as I don't think it is used in the sample). Where am I going wrong?
____________________________________________________________Programmers Resource Central
Advertisement
Hi Tera_Dragon,

I'm glad you've decided to try out AngelScript. I'll do my best to make it as easy for you as possible.

You've made a few mistakes, otherwise you seem to have understood how AS works.

engine->RegisterGlobalFunction("void print(char)", asFUNCTION(print), asCALL_CDECL);


This line will return -10 (asINVALID_DECLARATION) as 'char' is an unknown type in AngelScript. Because of this, all subsequent calls to Build() or ExecuteString() will fail, since the engine configuration is invalid. You would have cought this if you had added error checking. I suggest you do it like this:

r = engine->RegisterGlobalFunction("void print(char)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );


Instead of char you could use uint8, or int8, but in AngelScript this is a number, not a character.

Once you fix this first error you will soon notice that you can't use strings in the script library, thus print("d") will always fail. This is because AngelScript doesn't have a default string type. If you look at the sample code you'll see a call to RegisterScriptString(), this is where the string type is registered with the engine. Once you add that call, you may change your print() function to the following:

void print(std::string &c){  std::cout << "print()" << c << std::endl;}


and register it with:

r = engine->RegisterGlobalFunction("void print(string ∈)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );


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

Thanks for the help [smile]
Doesn't AngleScript support a character data type?
____________________________________________________________Programmers Resource Central
EDIT: Fixed it. I made a typo on the second param for RegisterObjectMethod().
I just spent about an hour on that [bawling]


I'm now having some toruble with making an instance of a class from the script.
I'm using the same code as before (fixed) but have added this before the for loop:
void RegisterClass(asIScriptEngine *e){	r = e->RegisterObjectType("Printer", sizeof(Printer), asOBJ_CLASS_CD);	assert(r>=0);	r = e->RegisterObjectBehaviour("Printer", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Constructor), asCALL_CDECL_OBJLAST);	assert(r>=0);	r = e->RegisterObjectBehaviour("Printer", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor), asCALL_CDECL_OBJLAST);	assert(r>=0);	r = e->RegisterObjectMethod("Printer", "void ouput(int)", asMETHOD(Printer, output), asCALL_THISCALL);	assert(r>=0);}

This doesn't give any errors (thanks a lot for telling me about the assert function, it's extremly useful [smile]). But when I try to execute Print p; I get the "Invalid script statement." error.

I have this script:
void foo(){	Printer p;	p.output(5);}

The error occurs when the engine->Build() is called, and only when the p.output(5); is there.

[Edited by - Tera_Dragon on April 23, 2005 5:38:01 PM]
____________________________________________________________Programmers Resource Central
There is no specific character type in AngelScript. I don't think it is necessary. uint8 and int8 are compatible with C++'s unsigned char and char though.

It's great that assert() is helping you out. Another helpful utility is asIOutputStream, with it you'll get specific error messages from the compilation. Here's an example:

class asCOutputStream : public asIOutputStream{public:  void Write(const char *text) { printf(text); }};...asCOutputStream out;int r = engine->Build(0, &out);orint r = engine->ExecuteString(0, script_string, &out);


It would have showed you that the method "output" wasn't registered.

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

Every time you want to execute a script function with asIScriptContext::Execute() do you have to call asIScriptContext::Prepare() first? eg you can't prepare a function and then execute it twice in a row without preparing it again?
____________________________________________________________Programmers Resource Central
You have to call Prepare(), because this reinitializes internal states. You may call Execute() multiple times wihtout Prepare() if the script execution was suspended before it finishes, that would then continue the execution where it last stopped.

If you intend to call the same script functions multiple times, you may use Prepare(-1), which prepares the last function again. It is sligthly faster than Preparing() with a true function ID. Also it might be a good idea to store the function IDs you intend to call instead of using engine->GetFunctionIdByDecl() all the time, since that call is rather expensive.

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

Quote: Original post by WitchLord
You may call Execute() multiple times wihtout Prepare() if the script execution was suspended before it finishes, that would then continue the execution where it last stopped.

When/why would this happen?
____________________________________________________________Programmers Resource Central
It never happens unless the application adds that functionality.

It could for example be an application registered function called from the script that suspends the execution. Or the application could use the line callback functionality to suspend the execution after a timeout, or at a specific line. You could also use a second application thread to suspend the execution of a script.

The execution is suspended with a call to asIScriptContext::Suspend().


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