Assertion failed on tempVariables.GetLength == 0

Started by
10 comments, last by dxj19831029 15 years, 8 months ago
Hi, I have this error when I run this code: print(current.f().Save.FieldName) Assertion error: Assertion failed! Program: File: ../../source/as_compiler.cpp Line: 461 Experssion: tempVariables.GetLength() == 0 I can ingore this error 4 times, the program can continue, but result is not wat I want. ....................................................... But if I run like this: {Chars a = current.f().Save.FieldName; print(a); } it works, print out wat I want. /////////////////////////////////////////////// typedef struct tagChars Chars; struct tagChars{ char* pointer; ....(some access methods here) }; f() is simply return a handle to an object. Save is POD object, only has values. print: can print out any object types. it works fine. ////////////// by the way, I am using version 2.3.1 ///////////////////////////////////////////////// Hope to hear from ur reply soon. Thanks.
Advertisement
This is obviously a bug in AngelScript. I'll look into it as soon as possible.

Thanks for reporting it.

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

Quote:Original post by WitchLord
This is obviously a bug in AngelScript. I'll look into it as soon as possible.

Thanks for reporting it.

Regards,
Andreas


Thank you very much!
I wasn't able to reproduce the assertion failure. Could you check my little test function that I wrote to see if I've registered everything like you do?

bool Test4(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	engine->RegisterObjectType("Chars", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectType("Struct", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectProperty("Struct", "Chars FieldName", 0);	engine->RegisterObjectType("TestObject2", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_FACTORY, "TestObject2@ f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_RELEASE, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectProperty("TestObject2", "Struct Save", 0); 	engine->RegisterObjectType("TestObject", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectMethod("TestObject", "TestObject2 @f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterGlobalFunction("void print(?&in)", asFUNCTION(0), asCALL_GENERIC);	const char *script1 = "void main() { TestObject current; print(current.f().Save.FieldName); }"; 	engine->AddScriptSection(0, "test", script1, strlen(script1));	r = engine->Build(0);	if( r < 0 )		fail = true;	const char *script2 = "void main() { TestObject current; Chars a = current.f().Save.FieldName; print(a); }";	engine->AddScriptSection(0, "test", script2, strlen(script2));	r = engine->Build(0);	if( r < 0 )		fail = true;	engine->Release();	return fail;}


Both scripts above compile just fine.

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

En, thanks for ur replaying!

I left my code in the company, it is a little different. I will compare on Monday, and see wat happens.
If still have problem, I will give u a sample code.

Thanks for ur quick replying.





Quote:Original post by WitchLord
I wasn't able to reproduce the assertion failure. Could you check my little test function that I wrote to see if I've registered everything like you do?

bool Test4(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	engine->RegisterObjectType("Chars", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectType("Struct", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectProperty("Struct", "Chars FieldName", 0);	engine->RegisterObjectType("TestObject2", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_FACTORY, "TestObject2@ f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_RELEASE, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectProperty("TestObject2", "Struct Save", 0); 	engine->RegisterObjectType("TestObject", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectMethod("TestObject", "TestObject2 @f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterGlobalFunction("void print(?&in)", asFUNCTION(0), asCALL_GENERIC);	const char *script1 = "void main() { TestObject current; print(current.f().Save.FieldName); }"; 	engine->AddScriptSection(0, "test", script1, strlen(script1));	r = engine->Build(0);	if( r < 0 )		fail = true;	const char *script2 = "void main() { TestObject current; Chars a = current.f().Save.FieldName; print(a); }";	engine->AddScriptSection(0, "test", script2, strlen(script2));	r = engine->Build(0);	if( r < 0 )		fail = true;	engine->Release();	return fail;}


Both scripts above compile just fine.


*****Type def:

typedef struct tagScriptObject ScriptObject;
typedef struct charPointer Chars;
typedef struct tagStruct Struct;


struct charPointer {
char* pointer;
charPointer() {pointer = NULL;}
charPointer(char *ptr) {pointer = ptr;}
char &setCharsFromChars(char *copy) {
//printf("Assign from chars to chars: self: %#X, from: %#X\n",this,copy);
// strcpy((char*)this,copy);
if (pointer == NULL) {
pointer = new char[strlen(copy)+1];
}
strcpy_s((char*)this, strlen(copy)+1, copy);
return *((char*)this);
}
void addRef() { return ;}
void release() { return ;}
};

typedef struct tagSave {
char * Value;

} _Save;

struct tagStruct {
_Save save;
void addRef() { return ;}
void release() { return ;}
};

struct tagScriptObject {
Struct *ptr;
tagScriptObject() {
ptr = NULL;
}
tagScriptObject(Struct *p) {
ptr = p;
}
Struct *getObject() {
return ptr;
}
};

void printChars(char *str) {
printf("%s", str);
}

char *Chars_Factory() {
return (char*) (new Chars());
}

Struct *Struct_Factory() {
return NULL;
}

***main applications:

int r, nRet;

// Create the script engine
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if( engine == 0 )
{
cout << "Failed to create script engine." << endl;
return -1;
}

// The script compiler will write any compiler messages to the callback.
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);

// Configure the script engine with all the functions,
// and variables that the script should be able to use.
//ConfigureEngine(engine);


nRet = engine->RegisterObjectType("Chars", sizeof(Chars), asOBJ_REF );
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ADDREF, "void f()", asMETHOD(Chars, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_RELEASE, "void f()", asMETHOD(Chars, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_FACTORY, "Chars@ f()", asFUNCTION(Chars_Factory), asCALL_CDECL);
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("_Save", sizeof(_Save), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectProperty("_Save", "Chars Value", offsetof(_Save, Value));
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("ScriptObject", sizeof(ScriptObject), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectType("Struct", sizeof(Struct), asOBJ_REF);
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_ADDREF, "void f()", asMETHOD(Struct, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_RELEASE, "void f()", asMETHOD(Struct, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_FACTORY, "Struct@ f()", asFUNCTION(Struct_Factory), asCALL_CDECL);
assert( nRet >= 0 );
// Chars = Chars
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ASSIGNMENT, "Chars &f(Chars &in)", asMETHOD(Chars,setCharsFromChars), asCALL_THISCALL);
assert( nRet >= 0 );

// Multiline
nRet = engine->RegisterObjectProperty("Struct", "_Save Save", offsetof(Struct, save));
assert( nRet >= 0 );

nRet = engine->RegisterObjectMethod("ScriptObject", "Struct@ f()", asMETHOD(ScriptObject, getObject), asCALL_THISCALL);
assert( nRet >= 0);


nRet = engine->RegisterGlobalFunction("void print(Chars &str)", asFUNCTION(printChars), asCALL_CDECL);
assert( nRet >= 0 );


Struct st;
st.save.Value = "Testing Testing";
ScriptObject so(&st);

nRet = engine->RegisterGlobalProperty("ScriptObject current", &so);
assert( nRet >= 0);
nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value;}",NULL);

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);



This code is similar to the one we used in our application. There is an error inside of code. It can not print out the Value string, instead of passing the pointer for the string, it passed the pointer of actuall struct object. It may be my error. Apart from it, the code above is exactly the same as I used our application.
Attention on the last two lines.

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

This suppose working properly.

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);

This will cause the assertion error I have described above.

I hope this helps.




Quote:Original post by WitchLord
I wasn't able to reproduce the assertion failure. Could you check my little test function that I wrote to see if I've registered everything like you do?

bool Test4(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	engine->RegisterObjectType("Chars", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectType("Struct", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectProperty("Struct", "Chars FieldName", 0);	engine->RegisterObjectType("TestObject2", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_FACTORY, "TestObject2@ f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_RELEASE, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectProperty("TestObject2", "Struct Save", 0); 	engine->RegisterObjectType("TestObject", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectMethod("TestObject", "TestObject2 @f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterGlobalFunction("void print(?&in)", asFUNCTION(0), asCALL_GENERIC);	const char *script1 = "void main() { TestObject current; print(current.f().Save.FieldName); }"; 	engine->AddScriptSection(0, "test", script1, strlen(script1));	r = engine->Build(0);	if( r < 0 )		fail = true;	const char *script2 = "void main() { TestObject current; Chars a = current.f().Save.FieldName; print(a); }";	engine->AddScriptSection(0, "test", script2, strlen(script2));	r = engine->Build(0);	if( r < 0 )		fail = true;	engine->Release();	return fail;}


Both scripts above compile just fine.
I got it working properly.


with this line:

nRet = engine->RegisterObjectMethod("ScriptObject", "Struct@ f()", asMETHOD(ScriptObject, getObject), asCALL_THISCALL);
assert( nRet >= 0);

I changed "Struct@ f()" into "Struct& f()", it works in our application.

Just wonder what is difference between them?

Thanks.


Quote:Original post by dxj19831029
*****Type def:

typedef struct tagScriptObject ScriptObject;
typedef struct charPointer Chars;
typedef struct tagStruct Struct;


struct charPointer {
char* pointer;
charPointer() {pointer = NULL;}
charPointer(char *ptr) {pointer = ptr;}
char &setCharsFromChars(char *copy) {
//printf("Assign from chars to chars: self: %#X, from: %#X\n",this,copy);
// strcpy((char*)this,copy);
if (pointer == NULL) {
pointer = new char[strlen(copy)+1];
}
strcpy_s((char*)this, strlen(copy)+1, copy);
return *((char*)this);
}
void addRef() { return ;}
void release() { return ;}
};

typedef struct tagSave {
char * Value;

} _Save;

struct tagStruct {
_Save save;
void addRef() { return ;}
void release() { return ;}
};

struct tagScriptObject {
Struct *ptr;
tagScriptObject() {
ptr = NULL;
}
tagScriptObject(Struct *p) {
ptr = p;
}
Struct *getObject() {
return ptr;
}
};

void printChars(char *str) {
printf("%s", str);
}

char *Chars_Factory() {
return (char*) (new Chars());
}

Struct *Struct_Factory() {
return NULL;
}

***main applications:

int r, nRet;

// Create the script engine
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if( engine == 0 )
{
cout << "Failed to create script engine." << endl;
return -1;
}

// The script compiler will write any compiler messages to the callback.
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);

// Configure the script engine with all the functions,
// and variables that the script should be able to use.
//ConfigureEngine(engine);


nRet = engine->RegisterObjectType("Chars", sizeof(Chars), asOBJ_REF );
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ADDREF, "void f()", asMETHOD(Chars, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_RELEASE, "void f()", asMETHOD(Chars, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_FACTORY, "Chars@ f()", asFUNCTION(Chars_Factory), asCALL_CDECL);
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("_Save", sizeof(_Save), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectProperty("_Save", "Chars Value", offsetof(_Save, Value));
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("ScriptObject", sizeof(ScriptObject), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectType("Struct", sizeof(Struct), asOBJ_REF);
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_ADDREF, "void f()", asMETHOD(Struct, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_RELEASE, "void f()", asMETHOD(Struct, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_FACTORY, "Struct@ f()", asFUNCTION(Struct_Factory), asCALL_CDECL);
assert( nRet >= 0 );
// Chars = Chars
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ASSIGNMENT, "Chars &f(Chars &in)", asMETHOD(Chars,setCharsFromChars), asCALL_THISCALL);
assert( nRet >= 0 );

// Multiline
nRet = engine->RegisterObjectProperty("Struct", "_Save Save", offsetof(Struct, save));
assert( nRet >= 0 );

nRet = engine->RegisterObjectMethod("ScriptObject", "Struct@ f()", asMETHOD(ScriptObject, getObject), asCALL_THISCALL);
assert( nRet >= 0);


nRet = engine->RegisterGlobalFunction("void print(Chars &str)", asFUNCTION(printChars), asCALL_CDECL);
assert( nRet >= 0 );


Struct st;
st.save.Value = "Testing Testing";
ScriptObject so(&st);

nRet = engine->RegisterGlobalProperty("ScriptObject current", &so);
assert( nRet >= 0);
nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value;}",NULL);

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);



This code is similar to the one we used in our application. There is an error inside of code. It can not print out the Value string, instead of passing the pointer for the string, it passed the pointer of actuall struct object. It may be my error. Apart from it, the code above is exactly the same as I used our application.
Attention on the last two lines.

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

This suppose working properly.

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);

This will cause the assertion error I have described above.

I hope this helps.




Quote:Original post by WitchLord
I wasn't able to reproduce the assertion failure. Could you check my little test function that I wrote to see if I've registered everything like you do?

bool Test4(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	engine->RegisterObjectType("Chars", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectType("Struct", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectProperty("Struct", "Chars FieldName", 0);	engine->RegisterObjectType("TestObject2", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_FACTORY, "TestObject2@ f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_RELEASE, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectProperty("TestObject2", "Struct Save", 0); 	engine->RegisterObjectType("TestObject", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectMethod("TestObject", "TestObject2 @f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterGlobalFunction("void print(?&in)", asFUNCTION(0), asCALL_GENERIC);	const char *script1 = "void main() { TestObject current; print(current.f().Save.FieldName); }"; 	engine->AddScriptSection(0, "test", script1, strlen(script1));	r = engine->Build(0);	if( r < 0 )		fail = true;	const char *script2 = "void main() { TestObject current; Chars a = current.f().Save.FieldName; print(a); }";	engine->AddScriptSection(0, "test", script2, strlen(script2));	r = engine->Build(0);	if( r < 0 )		fail = true;	engine->Release();	return fail;}


Both scripts above compile just fine.



I am confusing now.

@ is handle, which is the same as pointer in C/C++, rite?
& is the same as & in C/C++, rite?

if it is, the original case should work as well. Plz correct me, if I got something wrong.


Quote:Original post by dxj19831029
I got it working properly.


with this line:

nRet = engine->RegisterObjectMethod("ScriptObject", "Struct@ f()", asMETHOD(ScriptObject, getObject), asCALL_THISCALL);
assert( nRet >= 0);

I changed "Struct@ f()" into "Struct& f()", it works in our application.

Just wonder what is difference between them?

Thanks.


Quote:Original post by dxj19831029
*****Type def:

typedef struct tagScriptObject ScriptObject;
typedef struct charPointer Chars;
typedef struct tagStruct Struct;


struct charPointer {
char* pointer;
charPointer() {pointer = NULL;}
charPointer(char *ptr) {pointer = ptr;}
char &setCharsFromChars(char *copy) {
//printf("Assign from chars to chars: self: %#X, from: %#X\n",this,copy);
// strcpy((char*)this,copy);
if (pointer == NULL) {
pointer = new char[strlen(copy)+1];
}
strcpy_s((char*)this, strlen(copy)+1, copy);
return *((char*)this);
}
void addRef() { return ;}
void release() { return ;}
};

typedef struct tagSave {
char * Value;

} _Save;

struct tagStruct {
_Save save;
void addRef() { return ;}
void release() { return ;}
};

struct tagScriptObject {
Struct *ptr;
tagScriptObject() {
ptr = NULL;
}
tagScriptObject(Struct *p) {
ptr = p;
}
Struct *getObject() {
return ptr;
}
};

void printChars(char *str) {
printf("%s", str);
}

char *Chars_Factory() {
return (char*) (new Chars());
}

Struct *Struct_Factory() {
return NULL;
}

***main applications:

int r, nRet;

// Create the script engine
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if( engine == 0 )
{
cout << "Failed to create script engine." << endl;
return -1;
}

// The script compiler will write any compiler messages to the callback.
engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);

// Configure the script engine with all the functions,
// and variables that the script should be able to use.
//ConfigureEngine(engine);


nRet = engine->RegisterObjectType("Chars", sizeof(Chars), asOBJ_REF );
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ADDREF, "void f()", asMETHOD(Chars, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_RELEASE, "void f()", asMETHOD(Chars, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_FACTORY, "Chars@ f()", asFUNCTION(Chars_Factory), asCALL_CDECL);
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("_Save", sizeof(_Save), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectProperty("_Save", "Chars Value", offsetof(_Save, Value));
assert( nRet >= 0 );


nRet = engine->RegisterObjectType("ScriptObject", sizeof(ScriptObject), asOBJ_POD | asOBJ_VALUE | asOBJ_APP_CLASS);
assert( nRet >= 0 );

nRet = engine->RegisterObjectType("Struct", sizeof(Struct), asOBJ_REF);
assert( nRet >= 0 );
// add ref
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_ADDREF, "void f()", asMETHOD(Struct, addRef), asCALL_THISCALL);
assert( nRet >= 0);
// realease
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_RELEASE, "void f()", asMETHOD(Struct, release), asCALL_THISCALL);
assert( nRet >= 0);
// register Shape factory
nRet = engine->RegisterObjectBehaviour("Struct", asBEHAVE_FACTORY, "Struct@ f()", asFUNCTION(Struct_Factory), asCALL_CDECL);
assert( nRet >= 0 );
// Chars = Chars
nRet = engine->RegisterObjectBehaviour("Chars", asBEHAVE_ASSIGNMENT, "Chars &f(Chars &in)", asMETHOD(Chars,setCharsFromChars), asCALL_THISCALL);
assert( nRet >= 0 );

// Multiline
nRet = engine->RegisterObjectProperty("Struct", "_Save Save", offsetof(Struct, save));
assert( nRet >= 0 );

nRet = engine->RegisterObjectMethod("ScriptObject", "Struct@ f()", asMETHOD(ScriptObject, getObject), asCALL_THISCALL);
assert( nRet >= 0);


nRet = engine->RegisterGlobalFunction("void print(Chars &str)", asFUNCTION(printChars), asCALL_CDECL);
assert( nRet >= 0 );


Struct st;
st.save.Value = "Testing Testing";
ScriptObject so(&st);

nRet = engine->RegisterGlobalProperty("ScriptObject current", &so);
assert( nRet >= 0);
nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value;}",NULL);

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);



This code is similar to the one we used in our application. There is an error inside of code. It can not print out the Value string, instead of passing the pointer for the string, it passed the pointer of actuall struct object. It may be my error. Apart from it, the code above is exactly the same as I used our application.
Attention on the last two lines.

nRet = engine->ExecuteString(NULL,"{Chars a = current.f().Save.Value; print(a);}",NULL);

This suppose working properly.

nRet = engine->ExecuteString(NULL,"print(current.f().Save.Value)", NULL);

This will cause the assertion error I have described above.

I hope this helps.




Quote:Original post by WitchLord
I wasn't able to reproduce the assertion failure. Could you check my little test function that I wrote to see if I've registered everything like you do?

bool Test4(){	bool fail = false;	COutStream out;	int r;	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);	engine->RegisterObjectType("Chars", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectType("Struct", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectProperty("Struct", "Chars FieldName", 0);	engine->RegisterObjectType("TestObject2", 0, asOBJ_REF);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_FACTORY, "TestObject2@ f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectBehaviour("TestObject2", asBEHAVE_RELEASE, "void f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterObjectProperty("TestObject2", "Struct Save", 0); 	engine->RegisterObjectType("TestObject", 4, asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	engine->RegisterObjectMethod("TestObject", "TestObject2 @f()", asFUNCTION(0), asCALL_GENERIC);	engine->RegisterGlobalFunction("void print(?&in)", asFUNCTION(0), asCALL_GENERIC);	const char *script1 = "void main() { TestObject current; print(current.f().Save.FieldName); }"; 	engine->AddScriptSection(0, "test", script1, strlen(script1));	r = engine->Build(0);	if( r < 0 )		fail = true;	const char *script2 = "void main() { TestObject current; Chars a = current.f().Save.FieldName; print(a); }";	engine->AddScriptSection(0, "test", script2, strlen(script2));	r = engine->Build(0);	if( r < 0 )		fail = true;	engine->Release();	return fail;}


Both scripts above compile just fine.


I've reproduced the problem now. It shouldn't be too long before I have fix ready. Thanks for the help.

The difference between @ and & in AngelScript is similar to the difference betwen * and & in C++. It's small, but significant. When you return a & from a function it tells AngelScript that the reference is owned by the application, and that it shouldn't be released by AngelScript. When you return a @ it tells AngelScript that the reference is passed on to AngelScript, so that it must be released when it is no longer used by AngelScript. A & reference also must not be null, whereas it is legal for a @ reference to be null.

From the applications point of view, the difference is that when returning a @ the application must account for the reference, i.e. call AddRef on the object, that it passes on to the script. Unless, of course the application won't keep its own reference, in this case it is not necessary to call AddRef.

In your case, as you're not using reference counting, there is really no difference from the application's point of view (except that & must not be null). But AngelScript still treats the two slightly differently, which you discovered by triggering the bug in the library.

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 ur help. I think I understand them.



Quote:Original post by WitchLord
I've reproduced the problem now. It shouldn't be too long before I have fix ready. Thanks for the help.

The difference between @ and & in AngelScript is similar to the difference betwen * and & in C++. It's small, but significant. When you return a & from a function it tells AngelScript that the reference is owned by the application, and that it shouldn't be released by AngelScript. When you return a @ it tells AngelScript that the reference is passed on to AngelScript, so that it must be released when it is no longer used by AngelScript. A & reference also must not be null, whereas it is legal for a @ reference to be null.

From the applications point of view, the difference is that when returning a @ the application must account for the reference, i.e. call AddRef on the object, that it passes on to the script. Unless, of course the application won't keep its own reference, in this case it is not necessary to call AddRef.

In your case, as you're not using reference counting, there is really no difference from the application's point of view (except that & must not be null). But AngelScript still treats the two slightly differently, which you discovered by triggering the bug in the library.

Regards,
Andreas


This topic is closed to new replies.

Advertisement