Pass array from script to C++ function


#1

I try to create an array in my script and pass it to a registered C++ function:

C++:

void accept(const std::vector<int> &v)
{
    std::cout << v.size() << std::endl;
}

// ...

engine.add(fun(&accept), "accept");

Script:

accept([1, 2]);

I get an error:

Error: "Error calling function 'accept'" With parameters: (const Vector) during evaluation at (script.chai 3, 1)

  Expected: (const class std::vector<int,class std::allocator<int> >)

  script.chai (3, 1) 'accept([1, 2])'

Is there some trick to make this work? I tried registering my array via bootstrap::standard_library::vector_type<std::vector<int>>("TestVector"), but it just changes the error text to Expected: (const TestVector) and nothing else.

This code, however, works fine:

var v = TestVector();
v.push_back(1);
accept(v);

but initializing vectors via push_back method looks tedious.


#2

I’ve recently been playing with this myself. Right now there is an undocumented feature in the develop branch that helps with creating automatic conversion operations from Vector (aka std::vector<Boxed_Value>) into a non-boxed (such as std::vector<int>).

For example usage of the undocumented feature:

It works quite well for value types, because it copies the data from ChaiScript into a new strongly typed vector.

I do not have anything else in the works for clean initialization of a strongly typed vector. But you could take advantage of both the vector_type and the vector_conversion to get something like:

var v = TestVector([1,2,3,4,5]);

This would create a new std::vector<Boxed_Value> then convert that to std::vector<int> and pass it to the copy constructor of TestVector.

Not ideal, but pretty clean.

For more background on user defined type conversions:


#3

So, as far as I understand, array copying is involved in the process anyhow, which is sad from the performance perspective. In my game engine I have various methods that accept arrays, for example Mesh::setVertices(). If I call it, for example, every frame to change the mesh, that would be even more significant performance hit than it currently is.


#4

Can you give me an example of what you need to do on each frame? That can help us make sure we are solving the right problem. (and perhaps an example of what you’d like the code to look like).


#5

There is really nothing special else to add to what I already said. Let’s say I have a mesh object available from my script, and a script function that is called every frame by the host program. In this function I might want to call mesh.setVertices(vertices) and pass it an updated array vertices to change the mesh (it is a procedural mesh; for instance, Unity3d works the same way: you assign vertices to a mesh every frame, which causes them to be re-uploaded to the GPU).

setVertices is defined as follows:

void Mesh::setVertices(const std::vector<Vector3>& vertices);

Somewhere inside this function there is a call:

glBufferData(..., vertices.data(), ...);

This of course bases on an assumption that a vector of Vector3 structs form a continuous chunk of memory and therefore can be safely passed to OpenGL as a buffer.

My concern is that an inevitable unboxing each time I pass an array to a function will cause a significant slowdown for arrays of a decent size. I could pass an array of Boxed_Value into this function, but then I wouldn’t be able to pass this array data to OpenGL the way I do it now, so it needs to be unboxed beforehand.

On the other hand I can make a wrapper for mesh data and just pass a reference to it and call its methods to update particular mesh vertex positions.


#6

I think your best bet is just to expose the highest level references / c++ functions as you can. I cannot think of a way that involves creating the Vector3 objects in ChaiScript that doesn’t involve a layer or two of boxing / unboxing.

I do have plans for speeding up the performance of boxing objects in general, but that’s probably still a couple of weeks away.

Either way, I’d be very interested to know what kind of performance you see, and if you project is open source I’ll work on use it as a test case for ChaiScript to optimize the performance.


#7

Thanks for the interest in my project, but it’s currently in such an early development stage that using it for measurements won’t make any sense :slight_smile: Also there are no particular performance tests yet.