JuliaInterop / CxxWrap.jl

Package to make C++ libraries available in Julia
Other
418 stars 67 forks source link

enhancement - call operator overload with lambda function #70

Closed nbecker closed 7 years ago

nbecker commented 7 years ago

Thanks for adding call operator overload!

Is it possible to enhance this to allow calling a lambda?

auto sum_t = mod.add_type(name); sum_t.method ([](accum_t & a, el_t s) { a(s); return a;});

nbecker commented 7 years ago

My c++ foo isn't up to it: I tried the following but it failed

  template<typename R, typename... ArgsT>
  TypeWrapper<T>& method(R (*f)(ArgsT...))
  {
    m_module.method("operator()", [f](T& obj, ArgsT... args) -> R { return f(args...); } )
      .set_name(detail::make_fname("CallOpOverload", m_ref_dt));
    m_module.method("operator()", [f](T& obj, ArgsT... args) -> R { return f(args...); } )
      .set_name(detail::make_fname("CallOpOverload", m_alloc_dt));
    return *this;
  }
summer.cc:24:3: note:   mismatched types 'R (*)(ArgsT ...)' and 'expose_sum(const char*, jlcxx::Module&) [with el_t = double]::<lambda(accum_t&, double)>'
   sum_t.method ([](accum_t & a, el_t s) { a(s); return a;});
   ^~~~~
nbecker commented 7 years ago

Also tried this, which compiles my lambda!, but crashes with stack overflow

  template<typename R, typename LambdaT, typename... ArgsT>
  TypeWrapper<T>& add_lambda(LambdaT&& lambda, R(LambdaT::*)(ArgsT...) const)
  {
    return method(std::function<R(ArgsT...)>(std::forward<LambdaT>(lambda)));
  }
  template<typename LambdaT>
  TypeWrapper<T>& method(LambdaT&& lambda)
  {
    return add_lambda(std::forward<LambdaT>(lambda), &LambdaT::operator());
  }
  template<typename R, typename... ArgsT>
  TypeWrapper<T>& method(R (*f)(T&, ArgsT...))
  {
    m_module.method("operator()", [f](T& obj, ArgsT... args) -> R { return f(obj, args...); } )
      .set_name(detail::make_fname("CallOpOverload", m_ref_dt));
    m_module.method("operator()", [f](T& obj, ArgsT... args) -> R { return f(obj, args...); } )
      .set_name(detail::make_fname("CallOpOverload", m_alloc_dt));
    return *this;
  }
barche commented 7 years ago

OK, should be in master now! Note that you have to explicitly specify the target object as the first argument to the lambda.

nbecker commented 7 years ago

Thanks! Works perfectly.