Class registration problem

Started by
11 comments, last by Maega 15 years, 2 months ago
I have registered a C++ class successfully (according to return codes), but when I try to use it in a script, I get an "Expected Identifier" error.

engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	int r = engine->SetMessageCallback(asMETHOD(CLoad, GetScriptError), this, asCALL_THISCALL); assert( r >= 0 );


	RegisterScriptString(engine);

	r = engine->RegisterObjectType("CEngine", sizeof(CEngine), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert( r >= 0 );

	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_CONSTRUCT, "void f()", asMETHOD(CLoad, Constructor), asCALL_THISCALL); assert(r >= 0);
	
	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_DESTRUCT, "void f()", asMETHOD(CLoad, Destructor), asCALL_THISCALL); assert(r >= 0);

	r = engine->RegisterObjectMethod("CEngine", "void ShowMessage(string &in)", asMETHOD(CEngine, ShowMessage), asCALL_THISCALL); assert( r >= 0 );

	r = engine->RegisterObjectMethod("CEngine", "void Find(string &in)", asMETHOD(CEngine, FindGame), asCALL_THISCALL); assert( r >= 0 );

	r = engine->RegisterObjectMethod("CEngine", "void LoadExtension(string &in)", asMETHOD(CEngine, Extension), asCALL_THISCALL); assert( r >= 0 );



Script

void main()
{

CEngine blah;

}


Am I doing something wrong? Also, is it a bad idea to have the registered construction and destruction functions in another class? I'm trying not to put Angelscript code inside the C++ class. Finally, if I leave the body of the void main function empty, asserts are raised. Why is that?
Advertisement
I don't see any error in your code. I'll have to look into this.

What version of AngelScript are you using? What compiler and OS are you running on?


The CLoad::Constructor and CLoad::Destructor must not try to access any members of CLoad because the this pointer will actually point to a CEngine object (uninitialized, in case of the constructor). If you follow that, it should work ok. Though I think it may be a bit confusing having it like this, and wouldn't recommend 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

Hello,

I am using the current stable release, not the WIP.

As for the CLoad part, all I'm doing is calling the constructor and destructor of the object. I don't do anything else.
OK. I'll look into these problems.

You may want to give the WIP a try. I've already made several bug fixes in it. Not sure if any of them is related to your problem, but they could be.

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

Hello,

I built revision 338 of the trunk and tried that. I still have the same problems.

For some reason I have a feeling it's something I'm doing wrong or people would have reported similar problems before.
I wrote the following test for 2.15.0:

class CEngine{public:	CEngine() {};	~CEngine() {};	void ShowMessage(std::string &) {}	void Find(std::string &) {}	void LoadExtension(std::string &) {}	void Constructor(void *p) {}	void Destructor(void *p) {}};bool Test2(){	bool fail = false;	COutStream out;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	int r = engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); assert( r >= 0 );	RegisterScriptString(engine);	r = engine->RegisterObjectType("CEngine", sizeof(CEngine), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert( r >= 0 );	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_CONSTRUCT, "void f()", asMETHOD(CEngine, Constructor), asCALL_THISCALL); assert(r >= 0);	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_DESTRUCT, "void f()", asMETHOD(CEngine, Destructor), asCALL_THISCALL); assert(r >= 0);	r = engine->RegisterObjectMethod("CEngine", "void ShowMessage(string &in)", asMETHOD(CEngine, ShowMessage), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectMethod("CEngine", "void Find(string &in)", asMETHOD(CEngine, Find), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectMethod("CEngine", "void LoadExtension(string &in)", asMETHOD(CEngine, LoadExtension), asCALL_THISCALL); assert( r >= 0 );	const char * script = 		"void main()   \n"		"{   \n"		"CEngine blah;  \n"		"}  \n";	asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);	mod->AddScriptSection("script", script);	r = mod->Build();	if( r < 0 )	{		fail = true;	}	engine->Release();	return fail;}


Running it doesn't show any of the problems you're reporting. Could you check to see if you're doing something different from what I have done above?

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 moved the constructor and destructor into the CEngine class.

Now I'm just crashing. The asserts also happen with an empty void main and when I have CEngine blah; inside the main.
I think the problem is with the constructor/destructor behaviour. Since my test only compiled the script, but didn't execute it I didn't notice an error that I made.

Since the constructor/destructor behaviours are implemented as class methods, the object pointer to work on is stored in the this pointer, not in any of the method arguments as I had implemented in my test. I changed this in my test, and also added a CEngine as global variable in the script to test this.

class CEngine{public:	CEngine() {};	~CEngine() {};	void ShowMessage(std::string &) {}	void Find(std::string &) {}	void LoadExtension(std::string &) {}	void Constructor() 	{		new(this) CEngine(); 	}	void Destructor() 	{ 		this->~CEngine(); 	}};bool Test2(){	bool fail = false;	COutStream out;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	int r = engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); assert( r >= 0 );	RegisterScriptString(engine);	r = engine->RegisterObjectType("CEngine", sizeof(CEngine), asOBJ_VALUE | asOBJ_APP_CLASS_CDA); assert( r >= 0 );	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_CONSTRUCT, "void f()", asMETHOD(CEngine, Constructor), asCALL_THISCALL); assert(r >= 0);	r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_DESTRUCT, "void f()", asMETHOD(CEngine, Destructor), asCALL_THISCALL); assert(r >= 0);	r = engine->RegisterObjectMethod("CEngine", "void ShowMessage(string &in)", asMETHOD(CEngine, ShowMessage), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectMethod("CEngine", "void Find(string &in)", asMETHOD(CEngine, Find), asCALL_THISCALL); assert( r >= 0 );	r = engine->RegisterObjectMethod("CEngine", "void LoadExtension(string &in)", asMETHOD(CEngine, LoadExtension), asCALL_THISCALL); assert( r >= 0 );	const char * script = 		"CEngine g;  \n"		"void main()   \n"		"{   \n"		"CEngine blah;  \n"		"}  \n";	asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);	mod->AddScriptSection("script", script);	r = mod->Build();	if( r < 0 )	{		fail = true;	}	engine->Release();	return fail;}


The above works, without presenting any of the problems you mentioned.


How have you implemented the constructor and destructor behaviour methods? I recommend you implement them as global functions, or static member methods, in which case they would look like this:

class CLoad{  static Constructor(void *p)  {    new(p) CEngine();  }  static Destructor(CEngine *p)  {    p->~CEngine();  }}r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CLoad::Constructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );r = engine->RegisterObjectBehaviour("CEngine", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CLoad::Destructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );


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

While the asserts still happen, moving the constructor and destructor to global functions seems to have fixed the other problem.

Edit: Actually, I'm getting Unexpected Token '<unrecognized token>' with the line number beyond the end of the script when I try to call a registered function. Might be a different problem.
That last error is probably due to opening the script file in text mode, instead of binary mode. If opening the script file in text mode, the line endings may get translated from CRLF to just LF, thus producing a shorted script buffer than the file size.

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