Global variable problem.

Started by
12 comments, last by WitchLord 15 years, 5 months ago

ScriptObject selected;
bool restore() {
	FlexGridObject flex = current.searchChildByNameFromVW('LIST_FILES');
	//ScriptObject localSelected = selected;
	//CellPoint point = flex.getCoordinate(localSelected);
        CellPoint point = flex.getCoordinate(selected);
	return true;
}

	nRet = (asERetCodes) pScriptEngine->RegisterObjectMethod("FlexGridObject", "CellPoint getCoordinate(const ScriptObject &in)", asMETHODPR(FlexGridScript, getCoordinate, (ScriptObject &),CellPoint ), asCALL_THISCALL); 
	assert( nRet >= 0 );
The ScriptObject is registered as asOBJ_VALUE | asOBJ_APP_CLASS_CDA. The selected is the global variable. The comment lines are attempt to copy the global variabe to be local and pass into the function call. The problem here: * The getCoordinate method's argument becomes 0x00000004. when I set the break point inside of the method. * If I make a copy of the selected, and pass to the method, still have the same problem. Now, I tried use print before method getCoordinate called, it works perfrectly.

	nRet = (asERetCodes) pScriptEngine->RegisterGlobalFunction("void print(const ScriptObject &in)", asFUNCTION(printScriptObject), asCALL_CDECL);
	assert( nRet >= 0 );
Do u have any idea? Should I switch into ref type for all my data structure?
Advertisement
How is the CellPoint type implemented? And how is it registered?

Depending on how it is implemented and how it is registered you may have a mismatch in how AngelScript thinks it should send the ScriptObject reference and how C++ expects to receive it. Return values that are stored in memory, rather than in the registers, require a hidden parameter before the oficial parameters that gives the location where the function should put the return value.

My guess is that C++ expects the CellPoint type to be returned in memory (thus require the hidden parameter), but you've not registered the type correctly making AngelScript think the type will be returned in the registers. This would make C++ use the ScriptObject reference as the hidden parameter, and take whatever else is on the stack after that as the ScriptObject reference (the value 4 that you're seeing).

The fact that printScriptObject works properly makes this cause even more probable, since it returns void, thus don't expect any hidden parameter.

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

:).

nRet = (asERetCodes) pScriptEngine->RegisterObjectType("CellPoint", sizeof(CellPoint),    asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);	nRet = (asERetCodes) pScriptEngine->RegisterObjectProperty("CellPoint", "uint row", offsetof(CellPoint, row));	assert( nRet >= 0 );	nRet = (asERetCodes) pScriptEngine->RegisterObjectProperty("CellPoint", "uint column", offsetof(CellPoint, column));	assert( nRet >= 0 );


I register the CellPoint like this. Since I lazy to write all the constructor and deconstrutor for the cellpont.

I tried to register Cellpoint as asOBJ_VALUE | asOBJ_APP_CLASS_CDA, it works properly inside of application.

My question is: wat's difference between to use my old type registration and new one?

Since the Cellpoint is really a row and column, which both are int, so is there a way that I do not need to register the constructor, deconstructor, assignment operator? which the script will auto handle those? This is y I choose to register as a value+pod+primitive.

I try combination of value+pod, the script does not allow registration continue.

Any suggestion?

Thanks.

Quote:Original post by WitchLord
How is the CellPoint type implemented? And how is it registered?

Depending on how it is implemented and how it is registered you may have a mismatch in how AngelScript thinks it should send the ScriptObject reference and how C++ expects to receive it. Return values that are stored in memory, rather than in the registers, require a hidden parameter before the oficial parameters that gives the location where the function should put the return value.

My guess is that C++ expects the CellPoint type to be returned in memory (thus require the hidden parameter), but you've not registered the type correctly making AngelScript think the type will be returned in the registers. This would make C++ use the ScriptObject reference as the hidden parameter, and take whatever else is on the stack after that as the ScriptObject reference (the value 4 that you're seeing).

The fact that printScriptObject works properly makes this cause even more probable, since it returns void, thus don't expect any hidden parameter.

Regards,
Andreas


The asOBJ_APP_... flags tells AngelScript what type of object it is for C++. This is what allows AngelScript to handle the object properly when passing it to the application, or receiving it.

In your case you told AngelScript that the object is really a primitive of size 8, which is normally returned in registers. However to C++ it is a structure with a constructor (and possibly an assignment behaviour as well), and these types are returned in memory (thus the need for the hidden parameter).

This is documented in the manual on the page on registering value types.

A future version will allow registration of value types without specifying the asOBJ_APP_... flags, however when this is done you won't be able to pass/receive the type by value from native functions as AngelScript won't know how to properly handle them.

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

Is that mean if I declear the CellPoint struct in C++ as C, which will not have any constructor/deconstructor. That will work with my original registration as a primitive?

Em, it is safe that we register every class with asObj_APP tag. wat about the performance comparison with register as ref type in the script?


third question, If I register the struct/class in the script as asOBJ_APP_CLASS, do I need to provide the constructor/deconstrutor for it?
If not, does that mean I can only use it as a const &in type? does the script auto provide memcpy on the object which do not provide constructor/deconstructor?



thanks for ur help
Quote:Original post by WitchLord
The asOBJ_APP_... flags tells AngelScript what type of object it is for C++. This is what allows AngelScript to handle the object properly when passing it to the application, or receiving it.

In your case you told AngelScript that the object is really a primitive of size 8, which is normally returned in registers. However to C++ it is a structure with a constructor (and possibly an assignment behaviour as well), and these types are returned in memory (thus the need for the hidden parameter).

This is documented in the manual on the page on registering value types.

A future version will allow registration of value types without specifying the asOBJ_APP_... flags, however when this is done you won't be able to pass/receive the type by value from native functions as AngelScript won't know how to properly handle them.

Regards,
Andreas


A struct without any constructor/destructor/assignment behaviour should be registered with asOBJ_APP_CLASS (though I believe that for most compilers it would work with asOBJ_APP_PRIMITIVE as well).

Only value types should be registered with the asOBJ_APP_... flags. The reference types don't accept these flags, as they wouldn't be used by AngelScript anyway.

If you register the value type with asOBJ_POD, you don't have to provide any constructor or destructor. In this case AngelScript will also provide the default assignment behaviour for you.

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

Here is my registrations:
nRet = (asERetCodes) pScriptEngine->RegisterObjectType("CellPoint", sizeof(CellPoint), asOBJ_POD | asOBJ_VALUE /*asOBJ_APP_CLASS*/ /*asOBJ_VALUE | asOBJ_APP_CLASS*/);	assert( nRet >= 0 );nRet = (asERetCodes) pScriptEngine->RegisterObjectProperty("CellPoint", "uint row", offsetof(CellPoint, row));	assert( nRet >= 0 );	nRet = (asERetCodes) pScriptEngine->RegisterObjectProperty("CellPoint", "uint column", offsetof(CellPoint, column));	assert( nRet >= 0 );	// test if registeration crash the program	nRet = (asERetCodes) pScriptEngine->ExecuteString(NULL, "CellPoint a;", NULL);	assert( nRet >= 0 );

I tried the different combinations of asOBJ_POD, asOBJ_VALUE, asOBJ_APP_CLASS. asOBJ_POD | asOBJ_VALUE etc. None of them success, they either stop at register object type or stop at the last ExecuteString sentence.
Please correct me if I misunderstanding something?
we are using VS 2008, just in case you need to know the compiler.

Thanks for ur help.

Quote:Original post by WitchLord
A struct without any constructor/destructor/assignment behaviour should be registered with asOBJ_APP_CLASS (though I believe that for most compilers it would work with asOBJ_APP_PRIMITIVE as well).

Only value types should be registered with the asOBJ_APP_... flags. The reference types don't accept these flags, as they wouldn't be used by AngelScript anyway.

If you register the value type with asOBJ_POD, you don't have to provide any constructor or destructor. In this case AngelScript will also provide the default assignment behaviour for you.

Regards,
Andreas
Did you try this?

nRet = (asERetCodes) pScriptEngine->RegisterObjectType("CellPoint", sizeof(CellPoint), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);


This is assuming your CellPoint looks like this:

struct CellPoint{  unsigned int row;  unsigned int column;};


If the structure actually has a constructor, then you need to use the flag asOBJ_APP_CLASS_C instead (even if you don't want to register any constructor with the engine).

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

My bad!

I should try this. It works.

http://www.angelcode.com/angelscript/sdk/docs/manual/index.html
asOBJ_POD  A plain-old-data type. Only valid with asOBJ_VALUE 

I believe this is placed that confused me, you might want to change it so I point this out here. :) Because both of them are saying only valid with asObj_value, so ......

Anyway, thanks for your help!
:)


Quote:Original post by WitchLord
Did you try this?

nRet = (asERetCodes) pScriptEngine->RegisterObjectType("CellPoint", sizeof(CellPoint), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);


This is assuming your CellPoint looks like this:

struct CellPoint{  unsigned int row;  unsigned int column;};


If the structure actually has a constructor, then you need to use the flag asOBJ_APP_CLASS_C instead (even if you don't want to register any constructor with the engine).

Regards,
Andreas


Hmm, I would have hoped that the example code in the manual would show otherwise.

http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_val_type.html

The idea is that the asOBJ_POD flag is valid together with asOBJ_VALUE, but not with asOBJ_REF. It doesn't say that it is not valid together with the asOBJ_APP_... flags.

I will however see if I can improve the documentation to clarify this a bit more. Thanks for the tip.

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