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

Another bug, I think

Started by
10 comments, last by dxj19831029 15 years, 10 months ago
Here is the code: nRet = (asERetCodes) pScriptEngine->RegisterObjectType("_String", sizeof(_String), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(stringDefaultCoonstructor), asCALL_CDECL_OBJLAST); assert( nRet >= 0 ); //nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT, "void f()(const _String ∈)", asFUNCTION(stringCopyConstructor), asCALL_CDECL_OBJLAST); //nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_DESTRUCT, "void f(int)", asFUNCTION(stringINTConstructor), asCALL_CDECL_OBJLAST); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT, "void f(_String ∈ )", asFUNCTION(stringCopyConstructor), asCALL_CDECL_OBJLAST); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT, "void f(string ∈)", asFUNCTION(stringStringConstructor), asCALL_CDECL_OBJLAST); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(stringDecontructor), asCALL_CDECL_OBJLAST); assert( nRet >= 0 ); // = nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ASSIGNMENT, "_String &f(const string ∈ )", asMETHODPR(_String, operator=, (const string &), _String& ), asCALL_THISCALL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ASSIGNMENT, "_String &f(const _String ∈ )", asMETHODPR(_String, operator=, (const _String &), _String& ), asCALL_THISCALL); assert( nRet >= 0 ); // += nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ADD_ASSIGN , "_String &f(const string ∈ )", asMETHODPR(_String, operator+=, (const string &), _String& ), asCALL_THISCALL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ADD_ASSIGN , "_String &f(const _String ∈ )", asMETHODPR(_String, operator+=, (const _String &), _String& ), asCALL_THISCALL); assert( nRet >= 0 ); // comparison nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const _String ∈, const _String ∈)", asFUNCTION(compare_StringEqual), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const _String ∈, const string ∈)", asFUNCTION(compare_StringStringEqual), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const string ∈, const _String ∈)", asFUNCTION(compareString_StringEqual), asCALL_CDECL); assert( nRet >= 0 ); //nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const string ∈, const string ∈)", asFUNCTION(compareStringStringEqual), asCALL_CDECL); //assert( nRet >= 0 ); // not equal nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const _String ∈, const _String ∈)", asFUNCTION(compare_StringNotEqual), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const _String ∈, const string ∈)", asFUNCTION(compare_StringStringNotEqual), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const string ∈, const _String ∈)", asFUNCTION(compareString_StringNotEqual), asCALL_CDECL); assert( nRet >= 0 ); //nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const string ∈, const string ∈)", asFUNCTION(compareStringStringNotEqual), asCALL_CDECL); //assert( nRet >= 0 ); // + nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f( _String ∈, _String ∈)", asFUNCTION(operation_StringAdd), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f(const _String ∈, const string ∈)", asFUNCTION(operation_StringStringAdd), asCALL_CDECL); assert( nRet >= 0 ); nRet = (asERetCodes) pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f(const string ∈, const _String ∈)", asFUNCTION(operationString_StringAdd), asCALL_CDECL); assert( nRet >= 0 ); Exp: we have a our own _String class. It is very similar to std:string. U can use it to test. We did not use handle, instead we used Value + class + constructor and deconstructor. Everything going to be fine unless the Add operator. I test on == != +=. they are working properly. but with + operator on any combination: _String + string, _String + _String, string + _String is not working. I set the break point on the function, I found one of input is corrupted. For example: _String("ab") + "a". In the code: "a" + "fjdsklajfkldsaklfjdklsaj"(corrupted data); I set the break point in the constructor and deconstructor. It did not come to deconstructor before add operation. By the way, the script does not support: _String a; a+= "a" + "b" ; _String b = "c"; a += b + "c"; but it does support: string a; a+= "a" + "b"; string b = "c"; a += b + "c"; Can u help me on this? otherwise, I need to Create the reference counter and do the same registeration as string class. Cheers.
Advertisement
Just reposting your source code to get better formatting for easier review.

pScriptEngine->RegisterObjectType("_String", sizeof(_String),   asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT);pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT,    "void f()",                 asFUNCTION(stringDefaultCoonstructor), asCALL_CDECL_OBJLAST);	pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT,    "void f(_String &in )",		asFUNCTION(stringCopyConstructor), asCALL_CDECL_OBJLAST); pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_CONSTRUCT,    "void f(string &in)", asFUNCTION(stringStringConstructor), asCALL_CDECL_OBJLAST);pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_DESTRUCT,    "void f()", asFUNCTION(stringDecontructor), asCALL_CDECL_OBJLAST);	// = pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ASSIGNMENT,		"_String &f(const string &in )", asMETHODPR(_String, operator=, (const string &), _String& ), asCALL_THISCALL); pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ASSIGNMENT,		"_String &f(const _String &in )", asMETHODPR(_String, operator=, (const _String &), _String& ), asCALL_THISCALL); 	// +=pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ADD_ASSIGN ,		"_String &f(const string &in )", asMETHODPR(_String, operator+=, (const string &), _String& ), asCALL_THISCALL); pScriptEngine->RegisterObjectBehaviour("_String", asBEHAVE_ADD_ASSIGN ,		"_String &f(const _String &in )", asMETHODPR(_String, operator+=, (const _String &), _String& ), asCALL_THISCALL); 	// comparisonpScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const _String &in, const _String &in)", asFUNCTION(compare_StringEqual), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const _String &in, const string &in)", asFUNCTION(compare_StringStringEqual), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const string &in, const _String &in)", asFUNCTION(compareString_StringEqual), asCALL_CDECL);		// not equalpScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const _String &in, const _String &in)", asFUNCTION(compare_StringNotEqual), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const _String &in, const string &in)", asFUNCTION(compare_StringStringNotEqual), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_NOTEQUAL , "bool f(const string &in, const _String &in)", asFUNCTION(compareString_StringNotEqual), asCALL_CDECL);		// +pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f( _String &in,  _String &in)", asFUNCTION(operation_StringAdd), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f(const _String &in, const string &in)", asFUNCTION(operation_StringStringAdd), asCALL_CDECL);pScriptEngine->RegisterGlobalBehaviour(asBEHAVE_ADD , "_String f(const string &in, const _String &in)", asFUNCTION(operationString_StringAdd), asCALL_CDECL);



I don't see any obvious errors in your code. It may indeed be a bug in AngelScript. I'll have to investigate it.

You may however want to remove the asOBJ_POD from the type registration. Since your _String class obviously requires a constructor to be initialized, it is not a good idea to use this flag, since it tells AngelScript that the object memory doesn't require any special initialization. This shouldn't be the cause of the bug however, since you're apparently registering all the necessary behaviours.

Also, for some reason you've not registered all the behaviours to take const references as parameters. This wouldn't be an error from your side, however, it is possible that it is what triggers the bug. Try changing constructors and add behaviour to take the input parameter as const reference, and let me know if that helped in any way.

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

Sorry for that.
I just came to this forum, never know source tag before.

But I will do this better next time.

Is information enough? should I provide some more?

Thanks
Quote: Original post by WitchLord
Just reposting your source code to get better formatting.

*** Source Snippet Removed ***


I edited my previous post. Please re-read it for a possible work around.

This information should be enough to get me started on the investigating the potential bug. If I'm not able to reproduce it I'll post another message here to ask for more information.

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

:).
I used to put const, because it not working, so I tried to remove const and see wat happened.
Anyway, not working. :)


Quote: Original post by WitchLord
Just reposting your source code to get better formatting for easier review.

*** Source Snippet Removed ***


I don't see any obvious errors in your code. It may indeed be a bug in AngelScript. I'll have to investigate it.

You may however want to remove the asOBJ_POD from the type registration. Since your _String class obviously requires a constructor to be initialized, it is not a good idea to use this flag, since it tells AngelScript that the object memory doesn't require any special initialization. This shouldn't be the cause of the bug however, since you're apparently registering all the necessary behaviours.

Also, for some reason you've not registered all the behaviours to take const references as parameters. This wouldn't be an error from your side, however, it is possible that it is what triggers the bug. Try changing constructors and add behaviour to take the input parameter as const reference, and let me know if that helped in any way.

Regards,
Andreas


I found the problem. You need to change the flags used to register the type to:

asOBJ_VALUE | asOBJ_APP_CLASS_CDA


Actually, the real problem is that the asOBJ_APP_CLASS flag was missing (asOBJ_APP_CLASS_CDA is a combination of asOBJ_APP_CLASS, asOBJ_APP_CLASS_CONSTRUCTOR, asOBJ_APP_CLASS_DESTRUCTOR, and asOBJ_APP_CLASS_ASSIGNMENT).

I'll have to add an extra validation for this in AngelScript so that it can return a proper error code should this happen again.

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

So cool. I think I use documentation online.
I think it's out of date, is it? or I open the wrong link?



Quote: Original post by WitchLord
I found the problem. You need to change the flags used to register the type to:

asOBJ_VALUE | asOBJ_APP_CLASS_CDA


Actually, the real problem is that the asOBJ_APP_CLASS flag was missing (asOBJ_APP_CLASS_CDA is a combination of asOBJ_APP_CLASS, asOBJ_APP_CLASS_CONSTRUCTOR, asOBJ_APP_CLASS_DESTRUCTOR, and asOBJ_APP_CLASS_ASSIGNMENT).

I'll have to add an extra validation for this in AngelScript so that it can return a proper error code should this happen again.


nRet = (asERetCodes) pScriptEngine->RegisterStringFactory("_String", asFUNCTION(_StringFactory), asCALL_CDECL);  	assert( nRet >= 0 );


I try this, but the input to second parameter of _StringFactory is corrupted.

I register this after I registering string class. Is this the problem? Or I need to register the object as a ref?

Can I make a object to be
 asOBJ_REF | asOBJ_APP_CLASS_CDA 
?

Cheers.

Quote: Original post by dxj19831029
So cool. I think I use documentation online.
I think it's out of date, is it? or I open the wrong link?



Quote: Original post by WitchLord
I found the problem. You need to change the flags used to register the type to:

asOBJ_VALUE | asOBJ_APP_CLASS_CDA


Actually, the real problem is that the asOBJ_APP_CLASS flag was missing (asOBJ_APP_CLASS_CDA is a combination of asOBJ_APP_CLASS, asOBJ_APP_CLASS_CONSTRUCTOR, asOBJ_APP_CLASS_DESTRUCTOR, and asOBJ_APP_CLASS_ASSIGNMENT).

I'll have to add an extra validation for this in AngelScript so that it can return a proper error code should this happen again.
You can only have one string factory. So if you've already registered the string factory for std::string and you register again for _String, it will overwrite the previous string factory.

The string type doesn't have to be a reference type in order to work with string factory. Take a look at /sdk/tests/test_feature/source/stdstring.cpp for an example on how to register the std::string as a value type.

If you're using a similar implementation it could be because AngelScript thinks the _String type is returned in one way while C++ actually returns it in another way. If AngelScript thinks the type is returned in memory, but in reality it is returned in the registry by the application, then you'll get these corrupted parameters. Can you show me the class declaration for the _String type? I need to know the members in order to verify if you've used the correct flags while registering the type.



The online manual is a bit outdated, but not that much. I haven't been able to connect to the website via FTP to update it. But I'll get to that in time. The latest manual is always available in the SDK.

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 do not understand. It did not work yesterday, but it's working now.
It may because I did not clean up yesterday? No idea.

Thanks for the hint.

by the way, I tried to compile and run the test cases. None of them working (MSVC6 - 8).
It always have linking error.

I use VC 6++ and VC 2008.

Do u have any idea? Sorry for so many questions. I just swap from Java programming into C++.

1>------ Build started: Project: msvc8, Configuration: Debug Win32 ------1>Linking...1>   Creating library ../../bin\msvc8.lib and object ../../bin\msvc8.exp1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestFor::Test(void)" (?Test@TestFor@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestGetArgPtr::Test(void)" (?Test@TestGetArgPtr@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestScriptMath::Test(void)" (?Test@TestScriptMath@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestVarType::Test(void)" (?Test@TestVarType@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestDestructor::Test(void)" (?Test@TestDestructor@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestDictionary::Test(void)" (?Test@TestDictionary@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestBits::Test(void)" (?Test@TestBits@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestBool::Test(void)" (?Test@TestBool@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestSingleton::Test(void)" (?Test@TestSingleton@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestFactory::Test(void)" (?Test@TestFactory@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestRZ::Test(void)" (?Test@TestRZ@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestRegisterType::Test(void)" (?Test@TestRegisterType@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestAssign::Test(void)" (?Test@TestAssign@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestTypedef::Test(void)" (?Test@TestTypedef@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestInt8::Test(void)" (?Test@TestInt8@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestEnum::Test(void)" (?Test@TestEnum@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestCastOp::Test(void)" (?Test@TestCastOp@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestFile::Test(void)" (?Test@TestFile@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestRefCast::Test(void)" (?Test@TestRefCast@@YA_NXZ) referenced in function _main1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl TestImplicitCast::Test(void)" (?Test@TestImplicitCast@@YA_NXZ) referenced in function _main1>test_any.obj : error LNK2019: unresolved external symbol "public: int __thiscall CScriptAny::Release(void)" (?Release@CScriptAny@@QAEHXZ) referenced in function "void __cdecl TestAny::SetMyAny(class asIScriptGeneric *)" (?SetMyAny@TestAny@@YAXPAVasIScriptGeneric@@@Z)1>test_structintf.obj : error LNK2001: unresolved external symbol "public: int __thiscall CScriptAny::Release(void)" (?Release@CScriptAny@@QAEHXZ)1>test_any.obj : error LNK2019: unresolved external symbol "public: int __thiscall CScriptAny::AddRef(void)" (?AddRef@CScriptAny@@QAEHXZ) referenced in function "void __cdecl TestAny::SetMyAny(class asIScriptGeneric *)" (?SetMyAny@TestAny@@YAXPAVasIScriptGeneric@@@Z)1>test_any.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CScriptAny::Retrieve(void *,int)" (?Retrieve@CScriptAny@@QAE_NPAXH@Z) referenced in function "bool __cdecl TestAny::Test(void)" (?Test@TestAny@@YA_NXZ)1>test_scriptclassmethod.obj : error LNK2001: unresolved external symbol "public: bool __thiscall CScriptAny::Retrieve(void *,int)" (?Retrieve@CScriptAny@@QAE_NPAXH@Z)1>test_structintf.obj : error LNK2001: unresolved external symbol "public: bool __thiscall CScriptAny::Retrieve(void *,int)" (?Retrieve@CScriptAny@@QAE_NPAXH@Z)1>test_any.obj : error LNK2019: unresolved external symbol "public: int __thiscall CScriptAny::GetTypeId(void)" (?GetTypeId@CScriptAny@@QAEHXZ) referenced in function "bool __cdecl TestAny::Test(void)" (?Test@TestAny@@YA_NXZ)1>test_scriptclassmethod.obj : error LNK2001: unresolved external symbol "public: int __thiscall CScriptAny::GetTypeId(void)" (?GetTypeId@CScriptAny@@QAEHXZ)1>test_structintf.obj : error LNK2001: unresolved external symbol "public: int __thiscall CScriptAny::GetTypeId(void)" (?GetTypeId@CScriptAny@@QAEHXZ)1>test_any.obj : error LNK2019: unresolved external symbol "void __cdecl RegisterScriptAny(class asIScriptEngine *)" (?RegisterScriptAny@@YAXPAVasIScriptEngine@@@Z) referenced in function "bool __cdecl TestAny::Test(void)" (?Test@TestAny@@YA_NXZ)1>test_scriptclassmethod.obj : error LNK2001: unresolved external symbol "void __cdecl RegisterScriptAny(class asIScriptEngine *)" (?RegisterScriptAny@@YAXPAVasIScriptEngine@@@Z)1>test_scriptstring.obj : error LNK2019: unresolved external symbol "void __cdecl RegisterScriptStringUtils(class asIScriptEngine *)" (?RegisterScriptStringUtils@@YAXPAVasIScriptEngine@@@Z) referenced in function "bool __cdecl TestScriptString::Test(void)" (?Test@TestScriptString@@YA_NXZ)1>../../bin\msvc8.exe : fatal error LNK1120: 26 unresolved externals1>Build log was saved at "file://c:\work\script 2.3.1\sdk\tests\test_feature\projects\msvc8\Debug\BuildLog.htm"1>msvc8 - 33 error(s), 0 warning(s)========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========




Quote: Original post by WitchLord
You can only have one string factory. So if you've already registered the string factory for std::string and you register again for _String, it will overwrite the previous string factory.

The string type doesn't have to be a reference type in order to work with string factory. Take a look at /sdk/tests/test_feature/source/stdstring.cpp for an example on how to register the std::string as a value type.

If you're using a similar implementation it could be because AngelScript thinks the _String type is returned in one way while C++ actually returns it in another way. If AngelScript thinks the type is returned in memory, but in reality it is returned in the registry by the application, then you'll get these corrupted parameters. Can you show me the class declaration for the _String type? I need to know the members in order to verify if you've used the correct flags while registering the type.



The online manual is a bit outdated, but not that much. I haven't been able to connect to the website via FTP to update it. But I'll get to that in time. The latest manual is always available in the SDK.


This topic is closed to new replies.

Advertisement