Jump to content

  • Log In with Google      Sign In   
  • Create Account

Andreas Jonsson

Member Since 26 Mar 2000
Offline Last Active Yesterday, 06:57 AM

#5097871 Downcast application registered interface.

Posted by Andreas Jonsson on 30 September 2013 - 10:53 AM

Everything appears to be correct in how you've set things up, though there is one point that you left out that may be causing trouble:


Is the implementation of GetScriptBehaviour() increasing the ref counter on the returned script class? If it isn't then it is possible that the script object is destroyed too early which may be why the casts return null. Though I would imagine you would eventually experience an application crash if this was the case.



Assuming GetScriptBehaviour() is in fact increasing the ref counter, then the problem may be a bug in AngelScript. Can you set a break point in as_context.cpp on the asBC_Cast bytecode instruction and see why the VM is not able to successfully cast the object handle?

#5097372 Unsigned int64 wokring wrong

Posted by Andreas Jonsson on 27 September 2013 - 08:49 PM

I've fixed this problem in revision 1732.




#5096765 Why need to copy when using const T &in

Posted by Andreas Jonsson on 25 September 2013 - 01:59 PM

The real reason for &in and &out is to support sandboxing, which means that the script language must guarantee that references and handles are always valid.


In C++ it is quite easy to write code that invalidates a reference passed to a function. This is OK for C++ because the programmer is responsible for making sure everything is working ok, but with scripting it is not always possible to assume the script writer will be responsible (or even have a clear understanding over how things work).


// C++
vector<string> g_array;
void foo(string &value)
   value = "crash since the reference is no longer valid";
void main()


Within the script itself &in doesn't make much sense, since the end result is the same as passing the argument by value. But in order to maintain compatibility with C++ where many input arguments are passed by & for performance reason it is needed to differentiate between by value and input reference.


&out is needed as it is the only way a function can give additional return values.



Now, if you don't care about sand-boxing you can change the behaviour of AngelScript by setting the engine property asEP_ALLOW_UNSAFE_REFERENCES to true. When this is set you will be able to use &inout on all types, including primitives and registered value types, which makes it equivalent to C++.

#5096408 Unsigned int64 wokring wrong

Posted by Andreas Jonsson on 24 September 2013 - 08:06 AM

Hi Apmyp,


thanks for the bug report. I'll look into this and have it fixed as soon as I can.




#5095750 Bmfont outlined fonts

Posted by Andreas Jonsson on 21 September 2013 - 08:47 AM

Thanks for the compliments. 


I'll see if I can steal away some time from the AngelScript development to add these enhancements to BMFont. They have been on my to-do list for way too long already anyway.

#5095520 Calling overriden Mixin

Posted by Andreas Jonsson on 20 September 2013 - 11:22 AM

It's doable, but it would definitely not a trivial solution. I'll add a note on my to-do list to analyze this in detail for a possible future improvement.

#5095209 Script object reference in C++

Posted by Andreas Jonsson on 19 September 2013 - 10:56 AM

GetAddressOfVar() will return the address of the value in the variable. If the variable is a primitive type then the address will point to the value of the primitive, if the variable is a handle then the address will point to the handle, if the variable is local object (even if it is a ref type) then the address will point to the object.


You can use the typeId to know if the variable is a handle or not by checking for the bit asTYPEID_OBJHANDLE. If it is not a handle, then the variable will not be null.


I suggest you take a look at the CDebugger add-on in the SDK, particularly the ToString() and PrintValue() methods. It shows how to interpret the information you get about the variables.




#5094724 Register Parameter Names

Posted by Andreas Jonsson on 17 September 2013 - 01:22 PM

Yes, AngelScript doesn't store the name of the parameters for registered functions as it is not something that is needed by the engine.


You can use the user data in the function object to store the parameter names if you wish.




const char *decl = "void SetSize(int nRows, int nCols)";
r = engine->RegisterObjectMethod("Matrix", decl,
    asMETHODPR(Matrix, SetSize, (int,int), void), asCALL_THISCALL);
if( r > 0 )
   asIScriptFunction *func = engine->GetFunctionById(r);

#5094246 Ownership problem of Funcdefs.

Posted by Andreas Jonsson on 15 September 2013 - 10:16 AM

The asIScriptFunction object is the actual script code. As long as you don't discard the script module the function object will be valid. You do not need to increase the reference of the asIScriptFunction if you have control over when the script modules are discarded. If you want you can use the user data of the asIScriptFunction to receive a callback when the actual script function is being removed from the engine. With the callback you will then be able to cleanup any code that is still referencing the asIScriptFunction.







While I could theoretically change the built-in delegate object to use weak references it is currently not something I plan to do. Delegates can be used with application registered types as well, and not all application types are implemented to support weak references. 




#5094089 Ownership problem of Funcdefs.

Posted by Andreas Jonsson on 14 September 2013 - 04:07 PM

Hi Wracky,


If you don't want the delegate to hold a strong reference to the original object, then you'll need to look into implementing a weak-reference container.


Luckily for you, with version 2.27.1 weak references is already a reality, so it should be quite easy for you to do cool.png


I recommend you keep using the built-in delegates for allowing the script to pass the callback to the application, but instead of storing the received delegate directly, you dissect it and store the object pointer with a weak reference and the method pointer normally.


void FuncReceivingDelegate(asIScriptFunction *delegate)
   // Get the object pointer from the delegate
   if( delegate->GetFuncType() == asFUNC_DELEGATE )
     void *obj = delegate->GetDelegateObject();
     asIObjectType *objType = delegate->GetDelegateObjectType();
     asIScriptFunction *method = delegate->GetDelegateMethod();
     // Create a weak ref to keep the pointer to the object
     CScriptWeakRef *weakRefToDelegatedObject = new CScriptWeakRef(obj, objType);
     // Store the weak ref and the method instead of the original delegate


In case you wish to explore the generic funcdefs option, then you need to know that the generic handle add-on is capable of holding references to funcdefs too.




#5091630 Strange asOBJ_POD behavior with copy constructor and opAdd

Posted by Andreas Jonsson on 04 September 2013 - 02:24 PM

Whatever you do, do not try to trick to AngelScript. It will just cause difficult to find bugs as things don't quite work as it should in all cases. ph34r.png


Seriously, the asOBJ_APP_ flags must be registered correctly, as these are what AngelScript uses to know exactly how the host application expects to handle the type in the native calling convention. If you can, I recommend that you use the GetTypeTraits<T>() helper function. It will make sure you don't make a mistake in chosing the wrong flags.


A few flags cannot be determined automatically though, and these are asOBJ_APP_CLASS_ALLINTS, asOBJ_APP_CLASS_ALLFLOATS, and asOBJ_APP_CLASS_ALIGN8. On platforms that split value types in different CPU registers (e.g. 64bit Linux) these flags may be needed to tell AngelScript about the content of the type, so that it will be able to place the data in the correct CPU registers.


The manual explains what each flags means and how to use them.

#5091064 Strange asOBJ_POD behavior with copy constructor and opAdd

Posted by Andreas Jonsson on 02 September 2013 - 10:43 AM

It is all related to the native calling convention. In your first test you hadn't registered the Integer class correctly, which is why you were getting the wrong result. The original declaration should be registered with the flags asOBJ_APP_CLASS_C, not asOBJ_APP_CLASS_CK as it didn't have an explicit copy constructor.


When you explicitly declared the copy constructor in the Integer class the result was corrected as now the flag asOBJ_APP_CLASS_CK was correct.


If you're using a compiler with support for C++11 features (e.g. gnuc 4.7+, or MSVC 2012+), you can use the helper function GetTypeTraits<T>() to automatically determine the correct flags. For example:


#include <add_on/scripthelper/scripthelper.h>
r = _engine->RegisterObjectType("Integer", sizeof(Integer), asOBJ_VALUE | asOBJ_POD | GetTypeTraits<Integer>()); assert(r >= 0);


As for AngelScript calling or not calling the copy constructor, that is an optimization thing. There are still some places in the library where AngelScript will first create the object with the default constructor and then assign the value with the opAssign method. These are already on my to-do list to improve so that the copy constructor is called directly.



The btVector3 type has another trait that is not yet supported by AngelScript, and that is that the type is 16byte aligned (to optimize it for SIMD instructions). As such you cannot register this type as a value type. If you really want to use btVector3 directly in the scripts you need to register it as a scoped reference type, which will behave as a value type in the script, but is really allocated on the heap where it can be properly aligned to 16byte boundaries. Combine that with a memory pool for the allocation and deallocation of the vectors and you should not have any noticeable performance impacts.


Another option is that you avoid exposing the btVector3 type directly to the script, and instead use an ordinary unaligned structure for the vector3 type that the script will use. Of course, you will need to create wrappers for the functions that expect the btVector3 type, but hopefully you don't have too many of those exposed to the scripts.

#5090461 Reference Objects as Properties

Posted by Andreas Jonsson on 30 August 2013 - 03:37 PM

asOBJ_GC is necessary if the object can form circular references that will not be resolved by the application.


The classes TypeA, TypeB, and TypeC in your example can't form any circular references, 


If TypeA could hold a pointer to TypeC too, then a circular reference could be formed between TypeA and TypeC. If the application doesn't keep track of these and resolve them itself then the asOBJ_GC flag and related behaviours are necessary to avoid memory leaks.

#5090409 Reference Objects as Properties

Posted by Andreas Jonsson on 30 August 2013 - 11:39 AM

TypeB is complicated. TypeA is in this case used as a value type in C++ even though it is a reference type. Unless you implement the control to make sure TypeB stays alive as long as there are references to the member you'd do best not to expose this to the scripts at all. Instead I suggest that you use property accessors to allow the script to manipulate the TypeA member without directly accessing it.


For TypeC you're correct to use @. If you want to prevent that the pointer is reassigned, then ideally AngelScript should allow the member as &, but that is currently not supported. For now you'll need to use property accessors to make sure the script cannot reassign the handle. In this case you just need to expose a get accessor that returns the handle to the member.

#5088589 AngelScript 2.27.1 is here (so soon? yes)

Posted by Andreas Jonsson on 23 August 2013 - 10:02 PM

Maybe not the same syntax, but I definitely have plans to add support for variadic functions in the future.