From 5f8f5a1c333e57d5b57357ad8753a53db255bebc Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 19 Jan 2018 09:07:07 +0100 Subject: [PATCH] cppbind: More refactoring and finally getting rid of boost.preprocessor --- simgear/canvas/layout/NasalWidget.cxx | 9 +- simgear/nasal/cppbind/CMakeLists.txt | 4 +- simgear/nasal/cppbind/NasalContext.cxx | 20 +++ simgear/nasal/cppbind/NasalContext.hxx | 35 ++++- simgear/nasal/cppbind/NasalMe.hxx | 44 ++++++ simgear/nasal/cppbind/NasalMethodHolder.hxx | 75 ++++++++++ simgear/nasal/cppbind/NasalObject.hxx | 4 +- simgear/nasal/cppbind/NasalObjectHolder.hxx | 8 +- simgear/nasal/cppbind/cppbind_fwd.hxx | 54 ++++++++ .../detail/from_nasal_function_templates.hxx | 131 ------------------ .../cppbind/detail/from_nasal_helper.hxx | 78 +++-------- simgear/nasal/cppbind/from_nasal.hxx | 5 +- simgear/nasal/cppbind/test/TestContext.hxx | 2 +- simgear/nasal/cppbind/test/cppbind_test.cxx | 8 +- .../nasal/cppbind/test/cppbind_test_ghost.cxx | 4 +- 15 files changed, 267 insertions(+), 214 deletions(-) create mode 100644 simgear/nasal/cppbind/NasalMe.hxx create mode 100644 simgear/nasal/cppbind/NasalMethodHolder.hxx create mode 100644 simgear/nasal/cppbind/cppbind_fwd.hxx delete mode 100644 simgear/nasal/cppbind/detail/from_nasal_function_templates.hxx diff --git a/simgear/canvas/layout/NasalWidget.cxx b/simgear/canvas/layout/NasalWidget.cxx index 65ded50b..9e984642 100644 --- a/simgear/canvas/layout/NasalWidget.cxx +++ b/simgear/canvas/layout/NasalWidget.cxx @@ -189,10 +189,10 @@ namespace canvas if( hfw.empty() ) return -1; - naContext c = naNewContext(); try { - return hfw(nasal::to_nasal(c, const_cast(this)), w); + nasal::Context ctx; + return hfw(ctx.to_me(const_cast(this)), w); } catch( std::exception const& ex ) { @@ -202,7 +202,6 @@ namespace canvas "NasalWidget.heightForWidth: callback error: '" << ex.what() << "'" ); } - naFreeContext(c); return -1; } @@ -262,8 +261,8 @@ namespace canvas try { - nasal::Context c; - _set_geometry(nasal::to_nasal(c, this), rect); + nasal::Context ctx; + _set_geometry(ctx.to_me(this), rect); _flags &= ~LAYOUT_DIRTY; } catch( std::exception const& ex ) diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt index d25679a6..08f09937 100644 --- a/simgear/nasal/cppbind/CMakeLists.txt +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -1,10 +1,13 @@ include (SimGearComponent) set(HEADERS + cppbind_fwd.hxx Ghost.hxx NasalCallContext.hxx NasalContext.hxx NasalHash.hxx + NasalMe.hxx + NasalMethodHolder.hxx NasalObject.hxx NasalObjectHolder.hxx NasalString.hxx @@ -13,7 +16,6 @@ set(HEADERS ) set(DETAIL_HEADERS - detail/from_nasal_function_templates.hxx detail/from_nasal_helper.hxx detail/nasal_traits.hxx detail/to_nasal_helper.hxx diff --git a/simgear/nasal/cppbind/NasalContext.cxx b/simgear/nasal/cppbind/NasalContext.cxx index fe0e4755..dbbaa7c5 100644 --- a/simgear/nasal/cppbind/NasalContext.cxx +++ b/simgear/nasal/cppbind/NasalContext.cxx @@ -56,6 +56,26 @@ namespace nasal return String(_ctx, str); } + //---------------------------------------------------------------------------- + naRef ContextWrapper::callMethod( Me me, + naRef code, + std::initializer_list args ) + { + naRef ret = naCallMethodCtx( + _ctx, + code, + me, + args.size(), + const_cast(args.begin()), + naNil() // locals + ); + + if( const char* error = naGetError(_ctx) ) + throw std::runtime_error(error); + + return ret; + } + //---------------------------------------------------------------------------- naRef ContextWrapper::newVector(std::initializer_list vals) { diff --git a/simgear/nasal/cppbind/NasalContext.hxx b/simgear/nasal/cppbind/NasalContext.hxx index d3a3aee5..4cbcc8cc 100644 --- a/simgear/nasal/cppbind/NasalContext.hxx +++ b/simgear/nasal/cppbind/NasalContext.hxx @@ -19,13 +19,14 @@ #ifndef SG_NASAL_CONTEXT_HXX_ #define SG_NASAL_CONTEXT_HXX_ -#include "from_nasal.hxx" -#include "to_nasal.hxx" +#include "cppbind_fwd.hxx" +#include "NasalMe.hxx" + +#include +#include namespace nasal { - class Hash; - class String; /** * Wraps a nasal ::naContext without taking ownership/managing its lifetime @@ -63,12 +64,18 @@ namespace nasal return nasal::to_nasal(_ctx, arg); } - template + template naRef to_nasal(const T(&array)[N]) const { return nasal::to_nasal(_ctx, array); } + template + Me to_me(T arg) const + { + return Me{ to_nasal(arg) }; + } + template typename from_nasal_ptr::return_type from_nasal(naRef ref) const @@ -76,6 +83,21 @@ namespace nasal return (*from_nasal_ptr::get())(_ctx, ref); } + naRef callMethod(Me me, naRef code, std::initializer_list args); + + template + Ret callMethod( Me me, + naRef code, + typename boost::call_traits::param_type ... args ) + { + // TODO warn if with Ret == void something different to nil is returned? + return from_nasal(callMethod( + me, + code, + { to_nasal::param_type>(args)... } + )); + } + protected: naContext _ctx; @@ -100,4 +122,7 @@ namespace nasal } // namespace nasal +#include "from_nasal.hxx" +#include "to_nasal.hxx" + #endif /* SG_NASAL_CONTEXT_HXX_ */ diff --git a/simgear/nasal/cppbind/NasalMe.hxx b/simgear/nasal/cppbind/NasalMe.hxx new file mode 100644 index 00000000..953a372e --- /dev/null +++ b/simgear/nasal/cppbind/NasalMe.hxx @@ -0,0 +1,44 @@ +///@file +// +// Copyright (C) 2018 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_NASAL_ME_HXX_ +#define SG_NASAL_ME_HXX_ + +#include + +namespace nasal +{ + + /** + * Wrap a naRef to indicate it references the self/me object in Nasal method + * calls. + */ + struct Me + { + naRef _ref; + + explicit Me(naRef ref = naNil()): + _ref(ref) + {} + + operator naRef() { return _ref; } + }; + +} // namespace nasal + +#endif /* SG_NASAL_ME_HXX_ */ diff --git a/simgear/nasal/cppbind/NasalMethodHolder.hxx b/simgear/nasal/cppbind/NasalMethodHolder.hxx new file mode 100644 index 00000000..74c1a90a --- /dev/null +++ b/simgear/nasal/cppbind/NasalMethodHolder.hxx @@ -0,0 +1,75 @@ +///@file +// +// Copyright (C) 2018 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_NASAL_METHOD_HOLDER_HXX_ +#define SG_NASAL_METHOD_HOLDER_HXX_ + +#include "NasalContext.hxx" +#include "NasalObjectHolder.hxx" + +namespace nasal +{ + + /** + * Hold any callable function in Nasal and call it from C++ + */ + template + class NasalMethodHolder + { + using Holder = ObjectHolder; + + public: + NasalMethodHolder(naRef code): + _code(Holder::makeShared(code)) + {} + + /** + * @brief Call the function with the given arguments + * + * If the first argument is nasal::Me it will be passed as 'me' object and + * not as argument. + */ + Ret operator()(Args ... args) + { + return call(args...); + } + + private: + Holder::Ref _code; + + template + Ret call(Me self, CArgs ... args) + { + nasal::Context ctx; + return ctx.callMethod( + self, + _code->get_naRef(), + args... + ); + } + + template + Ret call(CArgs ... args) + { + return call(Me{}, args...); + } + }; + +} // namespace nasal + +#endif /* SG_NASAL_METHOD_HOLDER_HXX_ */ diff --git a/simgear/nasal/cppbind/NasalObject.hxx b/simgear/nasal/cppbind/NasalObject.hxx index c48812cf..4d965d9c 100644 --- a/simgear/nasal/cppbind/NasalObject.hxx +++ b/simgear/nasal/cppbind/NasalObject.hxx @@ -52,11 +52,11 @@ namespace nasal return Ret(); Context ctx; - auto func = get_member>( + auto func = get_member>( ctx, _nasal_impl.get_naRef(), name ); if( func ) - return func(nasal::to_nasal(ctx, this), args...); + return func(Me(ctx.to_nasal(this)), args...); return Ret(); } diff --git a/simgear/nasal/cppbind/NasalObjectHolder.hxx b/simgear/nasal/cppbind/NasalObjectHolder.hxx index 9b36bcf7..23ab9a79 100644 --- a/simgear/nasal/cppbind/NasalObjectHolder.hxx +++ b/simgear/nasal/cppbind/NasalObjectHolder.hxx @@ -42,6 +42,8 @@ namespace nasal { public: + using Ref = SGSharedPtr>; + /** * @param obj Object to save */ @@ -84,7 +86,7 @@ namespace nasal * * @param obj Object to save */ - static SGSharedPtr > makeShared(naRef obj); + static Ref makeShared(naRef obj); protected: naRef _ref; @@ -155,10 +157,10 @@ namespace nasal //---------------------------------------------------------------------------- template - SGSharedPtr > + typename ObjectHolder::Ref ObjectHolder::makeShared(naRef obj) { - return SGSharedPtr >( new ObjectHolder(obj) ); + return Ref( new ObjectHolder(obj) ); } } // namespace nasal diff --git a/simgear/nasal/cppbind/cppbind_fwd.hxx b/simgear/nasal/cppbind/cppbind_fwd.hxx new file mode 100644 index 00000000..e081bddc --- /dev/null +++ b/simgear/nasal/cppbind/cppbind_fwd.hxx @@ -0,0 +1,54 @@ +///@file +/// Nasal C++ Bindings forward declarations +/// +// Copyright (C) 2018 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_NASAL_CPPBIND_FWD_HXX_ +#define SG_NASAL_CPPBIND_FWD_HXX_ + +#include +#include + +namespace nasal +{ + + class CallContext; + class Context; + class ContextWrapper; + class Hash; + class Me; + class Object; + class String; + + template + class Ghost; + + template + naRef to_nasal(naContext c, T arg); + + template + naRef to_nasal(naContext c, const T(&array)[N]); + + template + T from_nasal(naContext c, naRef ref); + + template + struct from_nasal_ptr; + +} // namespace nasal + +#endif /* SG_NASAL_CPPBIND_FWD_HXX_ */ diff --git a/simgear/nasal/cppbind/detail/from_nasal_function_templates.hxx b/simgear/nasal/cppbind/detail/from_nasal_function_templates.hxx deleted file mode 100644 index 83f1216b..00000000 --- a/simgear/nasal/cppbind/detail/from_nasal_function_templates.hxx +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef SG_FROM_NASAL_HELPER_HXX_ -# error Nasal cppbind - do not include this file! -#endif - -#ifndef SG_DONT_DO_ANYTHING -#define n BOOST_PP_ITERATION() - -#ifndef SG_BOOST_FUNCTION_FROM_NASAL_FWD -# define SG_CALL_TRAITS_PARAM(z, n, dummy)\ - typename boost::call_traits::param_type a##n -# define SG_CALL_ARG(z, n, dummy)\ - to_nasal::param_type>(ctx, a##n) - - template< - class Ret - BOOST_PP_ENUM_TRAILING_PARAMS(n, class A) - > - typename boost::disable_if, Ret>::type - callNasalMethod( const ObjectHolder* holder, - Me self - BOOST_PP_ENUM_TRAILING(n, SG_CALL_TRAITS_PARAM, 0) ) - { - naContext ctx = naNewContext(); -#if n - naRef args[n] = { - BOOST_PP_ENUM(n, SG_CALL_ARG, 0) - }; -#else - naRef* args = NULL; -#endif - - naRef result = - naCallMethodCtx(ctx, holder->get_naRef(), self, n, args, naNil()); - - const char* error = naGetError(ctx); - std::string error_str(error ? error : ""); - - Ret r = Ret(); - if( !error ) - r = from_nasal_helper(ctx, result, static_cast(0)); - - naFreeContext(ctx); - - if( error ) - throw std::runtime_error(error_str); - - return r; - } - - template< - class Ret - BOOST_PP_ENUM_TRAILING_PARAMS(n, class A) - > - typename boost::enable_if, Ret>::type - callNasalMethod( const ObjectHolder* holder, - Me self - BOOST_PP_ENUM_TRAILING(n, SG_CALL_TRAITS_PARAM, 0) ) - { - callNasalMethod< - naRef // do not do any conversion and just ignore the return value - // TODO warn if something different to nil is returned? - BOOST_PP_COMMA_IF(n) - BOOST_PP_ENUM_PARAMS(n, A) - > - ( - holder, - self - BOOST_PP_ENUM_TRAILING_PARAMS(n, a) - ); - } - -# undef SG_CALL_TRAITS_PARAM -# undef SG_CALL_ARG -#endif - - template< - class Ret - BOOST_PP_ENUM_TRAILING_PARAMS(n, class A) - > - typename boost::disable_if< - // free function if first argument is not nasal::Me or no argument at all - boost::is_same, - boost::function - >::type - boostFunctionFromNasal(naRef code, Ret (*)(BOOST_PP_ENUM_PARAMS(n, A))) -#ifdef SG_BOOST_FUNCTION_FROM_NASAL_FWD - ; -#else - { - return boost::bind - ( - &callNasalMethod, - ObjectHolder::makeShared(code), - boost::bind(naNil) - BOOST_PP_COMMA_IF(n) - BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(n), _) - ); - } -#endif - -#if n > 0 - template< - class Ret - BOOST_PP_ENUM_TRAILING_PARAMS(n, class A) - > - typename boost::enable_if< - // method if type of first argument is nasal::Me - boost::is_same, - boost::function - >::type - boostFunctionFromNasal(naRef code, Ret (*)(BOOST_PP_ENUM_PARAMS(n, A))) -#ifdef SG_BOOST_FUNCTION_FROM_NASAL_FWD - ; -#else - { - return boost::bind - ( - &callNasalMethod< - Ret - BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) - BOOST_PP_ENUM_SHIFTED_PARAMS(n, A) - >, - ObjectHolder::makeShared(code), - BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(n), _) - ); - } -#endif -#endif - -#undef n -#endif // SG_DONT_DO_ANYTHING diff --git a/simgear/nasal/cppbind/detail/from_nasal_helper.hxx b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx index 3cf03dd2..9eee0690 100644 --- a/simgear/nasal/cppbind/detail/from_nasal_helper.hxx +++ b/simgear/nasal/cppbind/detail/from_nasal_helper.hxx @@ -24,20 +24,15 @@ #include #include -#include +#include +#include +#include #include -#include #include #include #include -#include #include -#include -#include -#include -#include -#include #include #include @@ -76,27 +71,19 @@ namespace nasal std::string _msg; }; - /** - * Wrap a naRef to indicate it references the self/me object in Nasal method - * calls. - */ - struct Me - { - naRef _ref; - - Me(naRef ref = naNil()): - _ref(ref) - {} - - operator naRef() { return _ref; } - }; - /** * Simple pass through for unified handling also of naRef. */ inline naRef from_nasal_helper(naContext, naRef ref, const naRef*) { return ref; } + /** + * Ignore return value + */ + // TODO show some warning when something is returned but ignored? + inline void from_nasal_helper(naContext, naRef, const void*) + {} + /** * Convert Nasal string to std::string */ @@ -125,43 +112,33 @@ namespace nasal */ bool from_nasal_helper(naContext c, naRef ref, const bool*); - namespace detail - { -#define SG_BOOST_FUNCTION_FROM_NASAL_FWD -#define BOOST_PP_ITERATION_LIMITS (0, 9) -#define BOOST_PP_FILENAME_1 -#include BOOST_PP_ITERATE() -#undef SG_BOOST_FUNCTION_FROM_NASAL_FWD - } - /** * Convert a Nasal function to a boost::function with the given signature. * * @tparam Sig Signature of returned function (arguments and return value * are automatically converted using from_nasal/to_nasal) */ - template - boost::function - from_nasal_helper(naContext c, naRef ref, boost::function*) + template + boost::function + from_nasal_helper(naContext c, naRef ref, const boost::function*) { if( naIsNil(ref) ) - return boost::function(); + return {}; if( !naIsCode(ref) && !naIsCCode(ref) && !naIsFunc(ref) ) throw bad_nasal_cast("not a function"); - return detail::boostFunctionFromNasal(ref, static_cast(0)); + return NasalMethodHolder(ref); } - template - typename boost::enable_if< boost::is_function, - boost::function - >::type - from_nasal_helper(naContext c, naRef ref, Sig*) + template + boost::function + from_nasal_helper(naContext c, naRef ref, Ret (*const)(Args...)) { - return from_nasal_helper(c, ref, static_cast*>(0)); + return + from_nasal_helper(c, ref, static_cast*>(0)); } /** @@ -227,21 +204,6 @@ namespace nasal return SGRect(vec[0], vec[1], vec[2], vec[3]); } - // Helpers for wrapping calls to Nasal functions into boost::function - namespace detail - { - // Dummy include to add a build dependency on this file for gcc/CMake/etc. -#define SG_DONT_DO_ANYTHING -# include -#undef SG_DONT_DO_ANYTHING - - // Now the actual include (we are limited to 8 arguments (+me) here because - // boost::bind has an upper limit of 9) -#define BOOST_PP_ITERATION_LIMITS (0, 8) -#define BOOST_PP_FILENAME_1 -#include BOOST_PP_ITERATE() - } - } // namespace nasal #endif /* SG_FROM_NASAL_HELPER_HXX_ */ diff --git a/simgear/nasal/cppbind/from_nasal.hxx b/simgear/nasal/cppbind/from_nasal.hxx index cd9a9fe4..a5025827 100644 --- a/simgear/nasal/cppbind/from_nasal.hxx +++ b/simgear/nasal/cppbind/from_nasal.hxx @@ -21,6 +21,7 @@ #define SG_FROM_NASAL_HXX_ #include +#include namespace nasal { @@ -52,8 +53,8 @@ namespace nasal template struct from_nasal_ptr { - typedef typename boost::remove_const - < typename boost::remove_reference::type + typedef typename std::remove_const + < typename std::remove_reference::type >::type return_type; typedef return_type(*type)(naContext, naRef); diff --git a/simgear/nasal/cppbind/test/TestContext.hxx b/simgear/nasal/cppbind/test/TestContext.hxx index 5a90d590..2bc4e7a8 100644 --- a/simgear/nasal/cppbind/test/TestContext.hxx +++ b/simgear/nasal/cppbind/test/TestContext.hxx @@ -42,7 +42,7 @@ class TestContext: template T exec(const std::string& code) { - return from_nasal(execImpl(code, {})); + return from_nasal(execImpl(code, nasal::Me{})); } template diff --git a/simgear/nasal/cppbind/test/cppbind_test.cxx b/simgear/nasal/cppbind/test/cppbind_test.cxx index 397c4e35..f2c704ef 100644 --- a/simgear/nasal/cppbind/test/cppbind_test.cxx +++ b/simgear/nasal/cppbind/test/cppbind_test.cxx @@ -218,7 +218,7 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing ) // passed on to function typedef boost::function MeIntFunc; MeIntFunc fmeint = hash.get("func"); - BOOST_CHECK_EQUAL(fmeint(naNil(), 5), 5); + BOOST_CHECK_EQUAL(fmeint(Me{}, 5), 5); //---------------------------------------------------------------------------- // Test exposing classes to Nasal @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing ) typedef boost::function MemFunc; MemFunc fGetThis = c.from_nasal(thisGetter); BOOST_REQUIRE( fGetThis ); - BOOST_CHECK_EQUAL( fGetThis(derived), (unsigned long)d.get() ); + BOOST_CHECK_EQUAL( fGetThis(Me{derived}), (unsigned long)d.get() ); BasePtr d2( new DoubleDerived ); derived = c.to_nasal(d2); @@ -369,10 +369,10 @@ BOOST_AUTO_TEST_CASE( cppbind_misc_testing ) BOOST_CHECK_EQUAL( objects[2], d3 ); // Calling fallback setter for unset values - BOOST_CHECK_EQUAL( c.exec("me.test = 3;", derived), 3 ); + BOOST_CHECK_EQUAL( c.exec("me.test = 3;", Me{derived}), 3 ); // Calling generic (fallback) getter - BOOST_CHECK_EQUAL( c.exec("var a = me.get_test;", derived), + BOOST_CHECK_EQUAL( c.exec("var a = me.get_test;", Me{derived}), "generic-get" ); //---------------------------------------------------------------------------- diff --git a/simgear/nasal/cppbind/test/cppbind_test_ghost.cxx b/simgear/nasal/cppbind/test/cppbind_test_ghost.cxx index 85546946..45bf105b 100644 --- a/simgear/nasal/cppbind/test/cppbind_test_ghost.cxx +++ b/simgear/nasal/cppbind/test/cppbind_test_ghost.cxx @@ -218,13 +218,13 @@ BOOST_AUTO_TEST_CASE( bind_methods ) TestContext ctx; auto test = boost::make_shared(); - ctx.exec("me.set(1, \"s2\", \"s3\", 4);", ctx.to_nasal(test)); + ctx.exec("me.set(1, \"s2\", \"s3\", 4);", ctx.to_me(test)); BOOST_CHECK_EQUAL(test->arg1, 1); BOOST_CHECK_EQUAL(test->arg2, "s2"); BOOST_CHECK_EQUAL(test->arg3, "s3"); BOOST_CHECK_EQUAL(test->arg4, 4); - ctx.exec("me.setReverse(1, \"s2\", \"s3\", 4);", ctx.to_nasal(test)); + ctx.exec("me.setReverse(1, \"s2\", \"s3\", 4);", ctx.to_me(test)); BOOST_CHECK_EQUAL(test->arg1, 4); BOOST_CHECK_EQUAL(test->arg2, "s3"); BOOST_CHECK_EQUAL(test->arg3, "s2");