cppbind: Opimize convert fixed size arrays and more type_traits
This commit is contained in:
@@ -28,14 +28,13 @@
|
|||||||
#include <simgear/nasal/cppbind/NasalMe.hxx>
|
#include <simgear/nasal/cppbind/NasalMe.hxx>
|
||||||
#include <simgear/nasal/cppbind/NasalMethodHolder.hxx>
|
#include <simgear/nasal/cppbind/NasalMethodHolder.hxx>
|
||||||
#include <simgear/nasal/cppbind/NasalObjectHolder.hxx>
|
#include <simgear/nasal/cppbind/NasalObjectHolder.hxx>
|
||||||
|
#include <simgear/std/type_traits.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
#include <boost/utility/enable_if.hpp>
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -143,9 +142,7 @@ namespace nasal
|
|||||||
* Convert a Nasal number to a C++ numeric type
|
* Convert a Nasal number to a C++ numeric type
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
typename boost::enable_if< boost::is_arithmetic<T>,
|
std::enable_if_t<std::is_arithmetic<T>::value, T>
|
||||||
T
|
|
||||||
>::type
|
|
||||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||||
{
|
{
|
||||||
naRef num = naNumValue(ref);
|
naRef num = naNumValue(ref);
|
||||||
@@ -174,17 +171,39 @@ namespace nasal
|
|||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a Nasal vector to a std::array
|
||||||
|
*/
|
||||||
|
template<class T, std::size_t N>
|
||||||
|
std::array<T, N>
|
||||||
|
from_nasal_helper(naContext c, naRef ref, const std::array<T, N>*)
|
||||||
|
{
|
||||||
|
if( !naIsVector(ref) )
|
||||||
|
throw bad_nasal_cast("Not a vector");
|
||||||
|
|
||||||
|
if( naVec_size(ref) != N )
|
||||||
|
throw bad_nasal_cast(
|
||||||
|
"Expected vector with " + std::to_string(N) + " elements"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::array<T, N> arr;
|
||||||
|
|
||||||
|
for(std::size_t i = 0; i < N; ++i)
|
||||||
|
arr[i] = from_nasal_helper(c, naVec_get(ref, i), static_cast<T*>(0));
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a Nasal vector of 2 elements to a 2d vector
|
* Convert a Nasal vector of 2 elements to a 2d vector
|
||||||
*/
|
*/
|
||||||
template<class Vec2>
|
template<class Vec2>
|
||||||
typename boost::enable_if<is_vec2<Vec2>, Vec2>::type
|
std::enable_if_t<is_vec2<Vec2>::value, Vec2>
|
||||||
from_nasal_helper(naContext c, naRef ref, const Vec2*)
|
from_nasal_helper(naContext c, naRef ref, const Vec2*)
|
||||||
{
|
{
|
||||||
std::vector<double> vec =
|
auto vec =
|
||||||
from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
|
from_nasal_helper(c, ref, static_cast<std::array<double, 2>*>(0));
|
||||||
if( vec.size() != 2 )
|
|
||||||
throw bad_nasal_cast("Expected vector with two elements");
|
|
||||||
return Vec2(vec[0], vec[1]);
|
return Vec2(vec[0], vec[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,10 +213,8 @@ namespace nasal
|
|||||||
template<class T>
|
template<class T>
|
||||||
SGRect<T> from_nasal_helper(naContext c, naRef ref, const SGRect<T>*)
|
SGRect<T> from_nasal_helper(naContext c, naRef ref, const SGRect<T>*)
|
||||||
{
|
{
|
||||||
std::vector<double> vec =
|
auto vec =
|
||||||
from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
|
from_nasal_helper(c, ref, static_cast<std::array<double, 4>*>(0));
|
||||||
if( vec.size() != 4 )
|
|
||||||
throw bad_nasal_cast("Expected vector with four elements");
|
|
||||||
|
|
||||||
return SGRect<T>(vec[0], vec[1], vec[2], vec[3]);
|
return SGRect<T>(vec[0], vec[1], vec[2], vec[3]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,13 @@
|
|||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
#include <simgear/math/SGRect.hxx>
|
#include <simgear/math/SGRect.hxx>
|
||||||
#include <simgear/nasal/cppbind/cppbind_fwd.hxx>
|
#include <simgear/nasal/cppbind/cppbind_fwd.hxx>
|
||||||
|
#include <simgear/std/type_traits.hxx>
|
||||||
|
|
||||||
#include <boost/function/function_fwd.hpp>
|
#include <boost/function/function_fwd.hpp>
|
||||||
#include <boost/utility/enable_if.hpp>
|
|
||||||
#include <boost/call_traits.hpp>
|
#include <boost/call_traits.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <initializer_list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -75,11 +76,66 @@ namespace nasal
|
|||||||
|
|
||||||
naRef to_nasal_helper(naContext c, const free_function_t& func);
|
naRef to_nasal_helper(naContext c, const free_function_t& func);
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
naRef array_to_nasal(naContext c, const T* arr, size_t size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a fixed size array to a Nasal vector
|
||||||
|
*/
|
||||||
|
template<class T, size_t N>
|
||||||
|
naRef to_nasal_helper(naContext c, const T(&array)[N])
|
||||||
|
{
|
||||||
|
return detail::array_to_nasal(c, array, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a fixed size C++ array to a Nasal vector
|
||||||
|
*/
|
||||||
|
template<class T, size_t N>
|
||||||
|
naRef to_nasal_helper(naContext c, const std::array<T, N>& array)
|
||||||
|
{
|
||||||
|
return detail::array_to_nasal(c, array.data(), N);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a std::initializer_list to a Nasal vector
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
naRef to_nasal_helper(naContext c, std::initializer_list<T> list)
|
||||||
|
{
|
||||||
|
return detail::array_to_nasal(c, list.begin(), list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert std::vector to a Nasal vector
|
||||||
|
*/
|
||||||
|
template< template<class T, class Alloc> class Vector,
|
||||||
|
class T,
|
||||||
|
class Alloc
|
||||||
|
>
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_same<Vector<T,Alloc>, std::vector<T,Alloc>>::value,
|
||||||
|
naRef
|
||||||
|
>
|
||||||
|
to_nasal_helper(naContext c, const Vector<T, Alloc>& vec)
|
||||||
|
{
|
||||||
|
return detail::array_to_nasal(c, vec.data(), vec.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a std::map to a Nasal Hash
|
||||||
|
*/
|
||||||
|
template<class Value>
|
||||||
|
naRef to_nasal_helper(naContext c, const std::map<std::string, Value>& map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an enum value to the according numeric value
|
* Convert an enum value to the according numeric value
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
typename boost::enable_if< boost::is_enum<T>, naRef >::type
|
std::enable_if_t<std::is_enum<T>::value, naRef>
|
||||||
to_nasal_helper(naContext c, T val)
|
to_nasal_helper(naContext c, T val)
|
||||||
{
|
{
|
||||||
return naNum(val);
|
return naNum(val);
|
||||||
@@ -89,7 +145,7 @@ namespace nasal
|
|||||||
* Convert a numeric type to Nasal number
|
* Convert a numeric type to Nasal number
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
typename boost::enable_if< boost::is_arithmetic<T>, naRef >::type
|
std::enable_if_t<std::is_arithmetic<T>::value, naRef>
|
||||||
to_nasal_helper(naContext c, T num)
|
to_nasal_helper(naContext c, T num)
|
||||||
{
|
{
|
||||||
return naNum(num);
|
return naNum(num);
|
||||||
@@ -99,67 +155,40 @@ namespace nasal
|
|||||||
* Convert a 2d vector to Nasal vector with 2 elements
|
* Convert a 2d vector to Nasal vector with 2 elements
|
||||||
*/
|
*/
|
||||||
template<class Vec2>
|
template<class Vec2>
|
||||||
typename boost::enable_if<is_vec2<Vec2>, naRef>::type
|
std::enable_if_t<is_vec2<Vec2>::value, naRef>
|
||||||
to_nasal_helper(naContext c, const Vec2& vec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a std::map to a Nasal Hash
|
|
||||||
*/
|
|
||||||
template<class Value>
|
|
||||||
naRef to_nasal_helper(naContext c, const std::map<std::string, Value>& map);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a fixed size array to a Nasal vector
|
|
||||||
*/
|
|
||||||
template<class T, size_t N>
|
|
||||||
naRef to_nasal_helper(naContext c, const T(&array)[N]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert std::vector to Nasal vector
|
|
||||||
*/
|
|
||||||
template< template<class T, class Alloc> class Vector,
|
|
||||||
class T,
|
|
||||||
class Alloc
|
|
||||||
>
|
|
||||||
typename boost::enable_if< boost::is_same< Vector<T,Alloc>,
|
|
||||||
std::vector<T,Alloc>
|
|
||||||
>,
|
|
||||||
naRef
|
|
||||||
>::type
|
|
||||||
to_nasal_helper(naContext c, const Vector<T, Alloc>& vec)
|
|
||||||
{
|
|
||||||
naRef ret = naNewVector(c);
|
|
||||||
naVec_setsize(c, ret, static_cast<int>(vec.size()));
|
|
||||||
for(int i = 0; i < static_cast<int>(vec.size()); ++i)
|
|
||||||
naVec_set(ret, i, to_nasal_helper(c, vec[i]));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
template<class Vec2>
|
|
||||||
typename boost::enable_if<is_vec2<Vec2>, naRef>::type
|
|
||||||
to_nasal_helper(naContext c, const Vec2& vec)
|
to_nasal_helper(naContext c, const Vec2& vec)
|
||||||
{
|
{
|
||||||
// We take just double because in Nasal every number is represented as
|
return to_nasal_helper(c, {
|
||||||
// double
|
// We take just double because in Nasal every number is represented as
|
||||||
double nasal_vec[2] = {
|
// double
|
||||||
static_cast<double>(vec[0]),
|
static_cast<double>(vec[0]),
|
||||||
static_cast<double>(vec[1])
|
static_cast<double>(vec[1])
|
||||||
};
|
});
|
||||||
return to_nasal_helper(c, nasal_vec);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a SGRect to a Nasal vector with position and size of the rect
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
naRef to_nasal_helper(naContext c, const SGRect<T>& rect)
|
||||||
|
{
|
||||||
|
return to_nasal_helper(c, {
|
||||||
|
static_cast<double>(rect.x()),
|
||||||
|
static_cast<double>(rect.y()),
|
||||||
|
static_cast<double>(rect.width()),
|
||||||
|
static_cast<double>(rect.height())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
template<class T>
|
template<class T>
|
||||||
naRef to_nasal_helper(naContext c, const SGRect<T>& rect)
|
naRef detail::array_to_nasal(naContext c, const T* arr, size_t size)
|
||||||
{
|
{
|
||||||
std::vector<double> vec(4);
|
naRef ret = naNewVector(c);
|
||||||
vec[0] = rect.x();
|
naVec_setsize(c, ret, static_cast<int>(size));
|
||||||
vec[1] = rect.y();
|
for(int i = 0; i < static_cast<int>(size); ++i)
|
||||||
vec[2] = rect.width();
|
naVec_set(ret, i, to_nasal_helper(c, arr[i]));
|
||||||
vec[3] = rect.height();
|
return ret;
|
||||||
|
|
||||||
return to_nasal_helper(c, vec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -182,17 +211,6 @@ namespace nasal
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
template<class T, size_t N>
|
|
||||||
naRef to_nasal_helper(naContext c, const T(&array)[N])
|
|
||||||
{
|
|
||||||
naRef ret = naNewVector(c);
|
|
||||||
naVec_setsize(c, ret, static_cast<int>(N));
|
|
||||||
for(int i = 0; i < static_cast<int>(N); ++i)
|
|
||||||
naVec_set(ret, i, to_nasal_helper(c, array[i]));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace nasal
|
} // namespace nasal
|
||||||
|
|
||||||
#endif /* SG_TO_NASAL_HELPER_HXX_ */
|
#endif /* SG_TO_NASAL_HELPER_HXX_ */
|
||||||
|
|||||||
@@ -117,6 +117,51 @@ naRef f_derivedGetX(const Derived& d, naContext c)
|
|||||||
}
|
}
|
||||||
naRef f_freeFunction(nasal::CallContext c) { return c.requireArg<naRef>(0); }
|
naRef f_freeFunction(nasal::CallContext c) { return c.requireArg<naRef>(0); }
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template<class T, std::size_t N>
|
||||||
|
ostream& operator<<(ostream& strm, const array<T, N>& vec)
|
||||||
|
{
|
||||||
|
for(auto const& v: vec)
|
||||||
|
strm << "'" << v << "',";
|
||||||
|
return strm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( cppbind_arrays )
|
||||||
|
{
|
||||||
|
TestContext ctx;
|
||||||
|
|
||||||
|
naRef na_vec = ctx.to_nasal({1., 2., 3.42});
|
||||||
|
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||||
|
|
||||||
|
na_vec = ctx.to_nasal(std::initializer_list<double>({1., 2., 3.42}));
|
||||||
|
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||||
|
|
||||||
|
using arr_d3_t = std::array<double, 3>;
|
||||||
|
arr_d3_t std_arr = {1., 2., 3.42};
|
||||||
|
na_vec = ctx.to_nasal(std_arr);
|
||||||
|
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||||
|
|
||||||
|
double d_arr[] = {1., 2., 3.42};
|
||||||
|
na_vec = ctx.to_nasal(d_arr);
|
||||||
|
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||||
|
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(std_arr, ctx.from_nasal<arr_d3_t>(na_vec));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||||
{
|
{
|
||||||
TestContext c;
|
TestContext c;
|
||||||
|
|||||||
Reference in New Issue
Block a user