Jump to content
  • Advertisement
Sign in to follow this  
dxj19831029

Assertion failed on tempVariables.GetLength == 0

This topic is 3618 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
This is obviously a bug in AngelScript. I'll look into it as soon as possible.

Thanks for reporting it.

Regards,
Andreas

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.


Share this post


Link to post
Share on other sites
*****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.

Share this post


Link to post
Share on other sites
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.


Share this post


Link to post
Share on other sites

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.


Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!