Exposing members that are arrays


#1

I know in other posts it was suggested to not using raw arrays or pointers, but you also hinted that it might be possible.

I have the following example C++ code that I would like to script using Chai:

struct message_content{
  int field1;
  int field2;
  int field3[3];
};

void sendMessage(const message_content& msg)
{
  // encodes and sends the message
}

From my chai scripts I would like to be able to create and fill in a message_content struct and then call sendMessage(). (I will have a whole series of structs, senders and receiver functions that will form an automated test system).

At the moment the following code does not work for me:

chai.add(ch::user_type<message_content>(), "message_content");
chai.add(ch::constructor<message_content()>(), "message_content");
chai.add(ch::fun(&message_content::field1), "field1");
chai.add(ch::fun(&message_content::field2), "field2");
chai.add(ch::fun(&message_content::field3), "field3");

The last line fails to compile due to the std::ref() being created to an array @ handle_return.cpp(110).

Is there any sort of work around that will enable this sort of usecase. Unfortunately I don’t have any control over the structures that I am mapping as they are auto-generated from an interface definition system.

Thanks for the awesome project by the way. I was able to get a program up and running within about 10 mins including passing data back and forth between C++ and ChaiScript.


#2

That sounds like a bug in how I handle return values that are arrays. I’m kind of surprised the compiler is not automatically decaying the array into a pointer type. I’ll see what I can find, but my week has gotten very busy.


#3

Ok thanks for the update, I appreciate your time. I forgot to mention in my post that I’m using Visual Studio 2013.

On VS2013 you don’t seem to be able to take a std::ref to an array type. Take the following code:

int x[3];
auto xref = std::ref(x);

This fails to compile because internally the std::ref function creates a _Callable_obj struct that has a member function that returns T. This causes a compile error when T is int[3].

The above code does compile correctly on Clang 3.5 and GCC 4.9 (using coliru), but I haven’t been able to check that ChaiScript functions as intented given this type of argument on these compilers.


Poll: What's Next For ChaiScript?
#4

Has there been progress on this?
While i can compile when binding a class with an array-member, i cannot access it:
Error: “Can not find appropriate array lookup operator ‘[]’.” With parameters: (A6_f, const int)
or if used with var as index:
Error: “Can not find appropriate array lookup operator ‘[]’.” With parameters: (A6_f, int)


#5

I’m sorry, I forgot about this. I have some concern that it would cause issues with indexing into other pointer types, but I’ll see if I can address it with at least a helper function to register it or something…

-Jason


#6

it’d be enough for me. wouldn’t mind having to registering it as an array of numbers.
but without knowing about the internals - the error calls it A6_f, so it seems to already know that i meant it to be an array of 6 floats.
will add some get-funcs for now.
thanks for the swift reply.


#7

Can you post a complete example? I might be able to work with that if it’s a fixed size array, or an std::array it’s the “treat a pointer as an array” that I have a problem with.


#8

In c++:

class ClientState {
public:
	timestamp_t timestamp;
	unsigned int buttons;
	float axes[6];
...

engine.add(chaiscript::user_type<ClientState>(),"ClientState");
engine.add(chaiscript::constructor < ClientState() > (),"ClientState");
engine.add(chaiscript::constructor < ClientState(const ClientState &) > (),"ClientState");
engine.add(chaiscript::fun(&ClientState::buttons),"buttons");
engine.add(chaiscript::fun(&ClientState::axes),"axes");

all is well, but later in script:

var cs = ClientState();
spc.getInputAtTime(ev.when,cs);
...
body.bodyDef.position.x = ppos.x+cs.axes[3]*0.1;

on the line that uses cs.axes[3]:

... failed: Error: "Can not find appropriate array lookup operator '[]'." With parameters: (A6_f, const int) 

so nothing fancy really, just a float[6] in a class, and using it only as an array.

edit: or do you mean complete as in compiles?


#9

One that compiles would be nice, but that answers my questions.


#10
#include <chaiscript/chaiscript.hpp>
class MyClass {
public:
	static const unsigned char numData = 10;
	float data[numData];
	MyClass() {
		for(unsigned char i = 0;i < numData;i++) data[i] = 0.0f;
	}
	MyClass(const MyClass & other) {*this = other;}
	MyClass & operator=(const MyClass & other) {
		for(unsigned char i = 0;i < numData;i++) data[i] = other.data[i];
	}
};


int main()
{
	chaiscript::ChaiScript chai;
	chai.add(chaiscript::user_type<MyClass>(),"MyClass");
	chai.add(chaiscript::constructor < MyClass() > (),"MyClass");
	chai.add(chaiscript::constructor < MyClass(const MyClass &) > (),"MyClass");
	chai.add(chaiscript::fun(&MyClass::data),"data");
	chai.eval("var myclass = MyClass();myclass.data[0] = 1.0f;");
}

// g++ -std=c++14 chaitest.cpp -o chaitest -ldl;./chaitest

/* result:
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Can not find appropriate array lookup operator '[]'." With parameters: (A10_f, const int) 
Aborted
*/

#11

Ok, I’ve got something that’s working - with a caveat. The code does not work on MSVC 2013 due to a bug in their implementation of std::reference_wrapper. It seems it will work in MSVC 2015 and I know that it works fine with gcc4.6+, clang3.4+

-Jason


#12

It’s done and merged into develop now.


#13

That’s great, thank you.


#14

If you go to use it, make sure to look at the example for how to expose an array type here:

You have to add the array element and tell the system about those types.