Show Changes Show Changes
Edit Edit
Print Print
Recent Changes Recent Changes
Subscriptions Subscriptions
Lost and Found Lost and Found
Find References Find References
Rename Rename
Administration Page Administration Page
Topic Locks Topic Locks

Search

History

2/22/2017 3:42:38 AM
-92.222.238.172
5/30/2007 12:37:56 PM
-125.72.28.38
5/28/2007 6:47:48 AM
-69.136.148.27
10/8/2006 8:23:42 PM
-66.27.77.187
8/2/2006 9:00:23 AM
-65.88.88.175
List all versions List all versions

RSS feed for the SquirrelWiki namespace

Sq Plus Get Set Objects
.
Summary

My motivation for this came from the following sort of situation.(http://www.horoskopmorgen.com/)

Imagine you have a function in a Squirrel script that looks something like this:

Vector3 doSomething(Vector3) {...}

If you want to call this function in c++, you'd use this:

// Get a reference to the 'returnFunction' function
SqPlus::SquirrelFunction doSomething(scriptNamespace, "doSomething");

// Execute it and catch the return value, which should be a Vector3 object
SquirrelObject returnObj = scriptFunction(Vector3(1,2,3));

Now that you're in c++, how do you get the Vector3 out of the returnObj? Now, I can hear you saying, "Why not just use the templated method that forces a particular return value? That would return a Vector3 or Vector3*, and solve the entire isssue."

And that's perfectly valid, if you know what the return value is going to be.

If you don't, you first need a way to check for the type that it is, and then a good way to get the value. Luckily, the ability to test for a particular type was added in SqPlus revision 17.

Here is how you can convert from a SquirrelObject to a type and back, throwing an error if the type does not match:

// Get any bound type from a SquirrelObject. Note that Squirrel's handling of references and pointers still holds here.
template<class _ty> static _ty Get(SquirrelObject& obj) {
    sq_pushobject(globalVM.GetVMHandle(),obj.GetObjectHandle());
    _ty val = SqPlus::Get(SqPlus::TypeWrapper<_ty>(),globalVM.GetVMHandle(),-1);
    sq_pop(globalVM.GetVMHandle(),1);
    return val;
}

// Set any bound type to a SquirrelObject. Note that Squirrel's handling of references and pointers still holds here.
template|class _ty| static SquirrelObject Set(_ty val) {
    SquirrelObject obj(globalVM.GetVMHandle());
    SqPlus::Push(globalVM.GetVMHandle(), val);
    obj.AttachToStackObject(-1);
    sq_pop(globalVM.GetVMHandle(),1);
    return obj;
}

This function assumes that VMs are treated as objects, as proposed in another change. Effectively, anywhere globalVM.GetVMHandle() appears, any method for obtaining the VM that the SquirrelObject belongs will work.

While this is a static function, it could also be made into a member variable of SquirrelObject, and this is the change that would be ideal, because users could do things like this:

Vector3 v(1,2,3);
SquirrelObject t; // Created from a VM, using the static namespace or a VM object.
t.Set(&v);

// It's also a small step from here to: SquirrelObject t(Vector3(1,2,3));
// and that would be pretty cool :-)

// Get a reference to the 'returnFunction' function
SqPlus::SquirrelFunction doSomething(scriptNamespace, "doSomething");

// Execute it and catch the return value, which should be a Vector3 object
SquirrelObject returnObj = scriptFunction(t);

Vector3* v_out( returnObj.Get<Vector3*>() );

The key here is that the functionality is exactly the same, but the signature of the scriptFunction is more generic. This has the benefit of allowing c++ stl containers to contain SquirrelFunctions with different signatures, so something like:

std::map<std::string,SqPlus::SquirrelFunction> callBacks;

Is possible, even if the callBacks all return different types.

Effectively, this change would make a SquirrelObject behave like Boost::Any for any bound types. The impact on the rest of SqPlus is minimal because these functions are templated. If my knowledge of compilers isn't failing me, that means that if they aren't used, they don't get compiled, so the code growth is minimized.

Added to release 24:

// From testSqPlus2.cpp:

void testSquirrelObjectSetGet(void) {
  float val = 1.234f;
  SquirrelObject t(val);

  float val2 = t.Get<float>();

  scprintf(_T("Val2 is: %f\n"),val2);

  if (1) {
#if 0
    SquirrelObject v(Vector3(1.f,2.f,3.f)); // Pass in by value: note how many times the object is created and destroyed.
#else
    SquirrelObject v(Vector3(1.f,2.f,3.f),true); // Pass in by reference instead of by copy ('true' arg). Only one temporary Vector3() is created and released.
#endif

    Vector3 * pv = v.Get<Vector3 *>();
    scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
    pv->z += 1.f;

    if (1) {
      SquirrelObject v2p(pv); // This is a pointer to v's instance. It will not get freed when v2p goes out of scope.
      pv = v2p.Get<Vector3 *>();
      scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
    } // if

  } // if

  scprintf(_T("Vector3() instance has been released.\n\n"));

} // testSquirrelObjectSetGet

See SquirrelObject.h for more information.

car insurance price quotes

Not logged in. Log in

squirrel's community wiki

This is FlexWiki, an open source wiki engine.

Change Style

Recent Topics