Boxed_Value and Vectors


#1

I was wondering if somebody could help me with a question regarding vectors and boxed_values.

I am attempting to call into a c++ function that takes a vector of integers. From reading other topics on this board it seems that chai vectors can be handled in mapped functions like so:

void mapped_function(std::vector<chaiscript::Boxed_Value> v)
{
  // Do stuff with v.
}

What is the best way to work with a Boxed_Value? I would like the user in the script to be able to call this function to pass in any type of integer, e.g.

mapped_function([1,2,3U])

If I call boxed_cast on each item in the vector it fails on the ‘3U’ value - Is there a way to generically get a boxed_value as a particular type? Boxed_cast seems to validate that the src and dst types are identical, which means I am unsure how to retrieve the value when I don’t know the exact type.


#2

You could do something like:

std::vector<int> to_vector_int(const std::vector<chaiscript::Boxed_Value> &vs) {
  std::vector<int> vi;
  std::transform(vs.begin(), vs.end(), std::back_inserter(vi), [](const Boxed_Value &bv) { return Boxed_Number(bv).get_as<int>(); });
  return vi;
}

Then if you want to get fancy you can then expose this function as an automatic translation function:

chai.add(chaiscript::type_conversion<std::vector<chaiscript::Boxed_Value>, std::vector<int>>(
  [](const std::vector<chaiscript::Boxed_Value> &t_bvs) { 
    return to_vector_int(t_bvs); 
  })
);

Then with these pieces in place you can expose your mapped function:

void mapped_function(const std::vector<int> &vi) {
  // do something with the vector
}

chai.add(fun(&mapped_function), "mapped_function") ;

// and now you can do something like

chai.eval("mapped_function([1,2,3,4u]);");

// which should call the converter function on its way to your mapped function automatically

Two notes:

  1. this code is off the cuff and untested, but it should work.
  2. There are some performance issues I’m currently working on with type conversions, so if you rely on this in a performance critical part of your code, you could have problems.

#3

Thanks for the very quick reply. Using

Boxed_Number(bv).get_as<int>();

Instead of Boxed_cast Was the key that I was missing.

I’ll experiment some more with the conversion functions, but I’m pretty happy at the moment simple running a conversion function in the C++ portion of code.


#4

Internally that extracts the Boxed_Value as the numeric type that it actually is, then static_cast<> it to the type you want. So any conversions that C++ would apply should be properly handled.

It’s the exact same method that’s used internally to chaiscript if you do something like

def myfun(double d) { }

myfun(1)

#5

This thread helped me get what I’m doing partially working, with this c++ code:

auto conv_uint = [](const vector<Boxed_Value>& vec) {
    vector<uint> ret;
    for (const auto& bv : vec) ret.emplace_back(boxed_cast<uint>(bv)); 
    return ret; 
}; m->add(type_conversion<vector<Boxed_Value>, vector<uint>>());

However, I have to do this in chaiscript:

foo.set_values([12u, 53u, 6u]);

But, what I want is to be able to do this:

foo.values = [12u, 53u, 6u];

How can I make this work? I prefer this interface because the I don’t need to add special setter functions into my C++ code.


#6

You didn’t post what error you are getting, but I’m guessing it’s a no appropriate operator = or similar error.

ChaiScript is able to do the required conversion, but you never told it how to assign. You can do this simply with:

m->add(fun([](vector<uint> &t_lhs, const vector<uint> &t_rhs) { return t_lhs = t_rhs; }), "=");

or you could use the booststrap_stl.hpp helpers to expose every feature of your vector<uint> type:

m->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint> >("VecUint"));

#7

Oh, I just realized that the lambda example there won’t compile with the last release yet. I’m working on better lambda support.

m->add(fun<vector<uint> &(vector<uint> &, const vector<uint> &)>([](vector<uint> &t_lhs, const vector<uint> &t_rhs) { return t_lhs = t_rhs; }), "=");

Is what you’d want to do with 5.7.0 or previous.


Pass array from script to C++ function