Sign in to follow this  
Wracky

Registering reference types.

Recommended Posts

Hi and thanks for reading. Angelscript allows for me to register an object in two ways. Value types for passing by value, and reference types that are constructed with a factory function and are ref-counted. I've been looking at the way reference types are to be registered, and it seemed to me like it was rather "intrusive" to the application. As I understand it, I'll have to add ref-counting to the objects itself. So add a create, addRef and Release function for the object. So I'll have to change my classes in order to work with angelscript. I could add a parent class to all my exported classes that does the ref counting, but what troubles me more, is that I'll have to update the ref count in the functions that use these objects. I understand that this is a safe way of doing things, and that lua's way of NOT doing this can cause problems with garbage collection. If Angescript would indeed natively support smartpointers in the future, I could register them as Value types, and it would certainly deminish the amount of classes I need to adapt for use with angelscript. So what I'd like to ask is: How can I integrate this type of script "binding" into my application with as little code changes as possible. And is there an "elegant" way to do this? Thanks!

Share this post


Link to post
Share on other sites
Rather than register reference types directly use a template class to wrap your types and have the template class add reference counting to your class. Something like:

template <typename T>
struct ObjectProxy {
ObjectProxy() : ref_cnt(1) {}
ObjectProxy(const ObjectProxy & other) : object(other.object), ref_cnt(1) {}
ObjectProxy & operator=(const ObjectProxy & other) {
object = rhs.object;
return *this;
}

template <typename A0>
ObjectProxy(const A0 & a0) : object(a0), ref_cnt(1) {}

template <typename A0, typename A1>
ObjectProxy(const A0 & a0, const A1 & a1) : object(a0, a1), ref_cnt(1) {}

void add_ref(void) { ++ref_cnt; }
void release(void) { if (--ref_cnt == 0) delete this; }

T object;
unsigned ref_cnt;
};

This is basically what CScriptString from the scriptstr add-on does; just templated so it can be used with types other than std::string.

Edit: you might want to look at the External Resources section of the AngelScript wiki. It contains a lot of code and other discussions of common (and not so common) issues working with AngelScript.

Share this post


Link to post
Share on other sites
Thanks for the reply.

I'm sorry but I'm not quite following your example.
If I was to make a templated class for adding refcounting to my own class, how would I go at registering this thing in angelscript?

Would that be something like:

engine->RegisterObjectBehaviour(
"foo",
asBEHAVE_FACTORY,
"ref@ f()",
asMETHOD(ObjectProxy<foo>, Create),
asCALL_THISCALL);


If this is possible, then I could register the rest of class Foo like normal, and it would still look a normal Foo class from the script point of view.
However if this is not possible... how would I go about calling functions of class Foo ?

I know you can bind global functions as if they were member functions of the registered c++ class.. but can this also be done with member functions from other classes ?

ofcourse then there's still the "problem" of ref counting when passing one of these babies to a function that takes a type Foo& as a parameter...

I don't actually have an AngelScript implementation just yet to try stuff out. Sorry 'bout that. But I wanna know a bit more about what to expect when starting with AngelScript.

Thanks!

Share this post


Link to post
Share on other sites
If you have a look at the CScriptString add-on in the AngelScript sdk, you'll see how the std::string is wrapped in a class that takes care of the reference counting. Most of the functions that access the std::string registered with the original std::string methods, thus avoiding the use of wrappers. You'll still have to write wrapper functions for those that need to manage the reference counting.

If you don't need or don't care about automatic memory management for your types you can just register the ADDREF and RELEASE behaviours with dummy functions that don't do anything. This would basically give you the same result as the user types in Lua.

Another way to add memory management is to place the reference counter in a separate structure, linked through a hash map to the management object. This is obviously rather slow, but will allow you to add reference counting to any object type without having to modify the actual code.

Depending on how the objects are used, you may not need to use reference counting at all. If the object cannot be instanciated, then you can just expose a reference to an object in the application that the script can manipulate directly. manual: single-ref type

One thing you'll have to think carefully about, regardless of the script library you choose, is how objects are transferred between script domain and application domain. If you can minimize the number of points where you'll have to care about this you'll make it a lot easier on yourself.



Share this post


Link to post
Share on other sites
Thanks for the tips! I indeed intend to design the interface in such a way that minimal object passing between script and application is required. Good OO design helps I think.

I'll go and fiddle around a bit with it. I don't yet see the full scope of what can be done with the way I can register classes and functions to angelscript, so I think I'll just go and make a few try-outs.

Thanks everyone!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this