JuliaInterop / libcxxwrap-julia

C++ library for backing CxxWrap.jl
Other
85 stars 43 forks source link

Problem with wrapping `static` functions with v0.12.0 #150

Closed ArseniyKholod closed 7 months ago

ArseniyKholod commented 7 months ago

Hello, I try to move one of the projects, that is wrapped by libcxxwrap-julia from version v0.11.2 to the latest one. And I encountered some problems, that could be issued by breaking changes introduced by @melven on v0.12.0.
In openfhe-julia we wrap using the following code the type PrivateKeyImpl.

#include "jlcxx/jlcxx.hpp"
#include "openfhe.h"

void wrap_PrivateKeyImpl(jlcxx::Module& mod) {
  // Source: <OpenFHE>/src/pke/include/key/privatekey.h
  // Note: This file already contains all functions (except constructors) that are defined
  //       in OpenFHE. For feature completeness, one only needs to implement the currently
  //       commented functions.
  mod.add_type<jlcxx::Parametric<jlcxx::TypeVar<1>>>("PrivateKeyImpl")
    .apply<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>>([](auto wrapped) {
        typedef typename decltype(wrapped)::type WrappedT;
        // wrapped.method("GetPrivateElement", &WrappedT::GetPrivateElement);
        // wrapped.method("SetPrivateElement", &WrappedT::SetPrivateElement);
        wrapped.method("operator==", &WrappedT::operator==);
        wrapped.method("operator!=", &WrappedT::operator!=);
        // wrapped.method("save", &WrappedT::save);
        // wrapped.method("load", &WrappedT::load);
        wrapped.method("SerializedObjectName", &WrappedT::SerializedObjectName);
        wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      });
}

The last line wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion); fails using libcxxwrap-julia starting with v0.12.0.

Part of the code that is wrapped:

template <class Element>
class PrivateKeyImpl : public Key<Element> {
   //....
    std::string SerializedObjectName() const {
        return "PrivateKey";
    }
    static uint32_t SerializedVersion() {
        return 1;
    }
    //....
};

wrapped.method("SerializedObjectName", &WrappedT::SerializedObjectName); works fine.

wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion); fails. The only essential reason between these two methods I see, that SerializedVersion is a static function.

Could it be the case, that changes between 0.11.2 and 0.12.0 introduced the problem with static methods? Thank you in advance!

Initial opened Issue: sloede/OpenFHE.jl#43 Comment with compiling commands: https://github.com/sloede/OpenFHE.jl/issues/43#issuecomment-2050332797 Used system: Ubuntu 20.04.6 LTS, The CXX compiler identification is GNU 10.5.0

Full error log:

kholod@pcm016:~/openfhe-julia/build$ make
Scanning dependencies of target openfhe_julia
[  4%] Building CXX object CMakeFiles/openfhe_julia.dir/src/openfhe_julia.cpp.o
[  8%] Building CXX object CMakeFiles/openfhe_julia.dir/src/enums.cpp.o
[ 12%] Building CXX object CMakeFiles/openfhe_julia.dir/src/nativeinteger.cpp.o
[ 16%] Building CXX object CMakeFiles/openfhe_julia.dir/src/ubint.cpp.o
[ 20%] Building CXX object CMakeFiles/openfhe_julia.dir/src/cryptocontextbfvrns.cpp.o
[ 25%] Building CXX object CMakeFiles/openfhe_julia.dir/src/cryptocontextbgvrns.cpp.o
[ 29%] Building CXX object CMakeFiles/openfhe_julia.dir/src/cryptocontextckksrns.cpp.o
[ 33%] Building CXX object CMakeFiles/openfhe_julia.dir/src/fheckksrns.cpp.o
[ 37%] Building CXX object CMakeFiles/openfhe_julia.dir/src/params.cpp.o
[ 41%] Building CXX object CMakeFiles/openfhe_julia.dir/src/ccparams.cpp.o
[ 45%] Building CXX object CMakeFiles/openfhe_julia.dir/src/serializable.cpp.o
[ 50%] Building CXX object CMakeFiles/openfhe_julia.dir/src/dcrtpoly.cpp.o
[ 54%] Building CXX object CMakeFiles/openfhe_julia.dir/src/privatekeyimpl.cpp.o
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp: In instantiation of ‘wrap_PrivateKeyImpl(jlcxx::Module&)::<lambda(auto:2)> [with auto:2 = jlcxx::TypeWrapper<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > > >]’:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1190:15:   required from ‘int jlcxx::TypeWrapper<T>::apply_internal(FunctorT&&) [with AppliedT = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >; FunctorT = wrap_PrivateKeyImpl(jlcxx::Module&)::<lambda(auto:2)>; T = jlcxx::Parametric<jlcxx::TypeVar<1> >]’
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1139:63:   required from ‘jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::apply(FunctorT&&) [with AppliedTypesT = {lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >}; FunctorT = wrap_PrivateKeyImpl(jlcxx::Module&)::<lambda(auto:2)>; T = jlcxx::Parametric<jlcxx::TypeVar<1> >]’
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:20:8:   required from here
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:19:23: error: no matching function for call to ‘jlcxx::TypeWrapper<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > > >::method(const char [34], uint32_t (*)())’
   19 |         wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/kholod/libcxxwrap-julia/install/include/jlcxx/jlcxx.hpp:15,
                 from /home/kholod/openfhe-julia/src/privatekeyimpl.cpp:1:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1082:19: note: candidate: ‘template<class R, class CT, class ... ArgsT, class ... Extra> jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(const string&, R (CT::*)(ArgsT ...), Extra ...) [with R = R; CT = CT; ArgsT = {ArgsT ...}; Extra = {Extra ...}; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1082 |   TypeWrapper<T>& method(const std::string& name, R(CT::*f)(ArgsT...), Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1082:19: note:   template argument deduction/substitution failed:
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:19:23: note:   mismatched types ‘R (CT::*)(ArgsT ...)’ and ‘uint32_t (*)()’ {aka ‘unsigned int (*)()’}
   19 |         wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/kholod/libcxxwrap-julia/install/include/jlcxx/jlcxx.hpp:15,
                 from /home/kholod/openfhe-julia/src/privatekeyimpl.cpp:1:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1091:19: note: candidate: ‘template<class R, class CT, class ... ArgsT, class ... Extra> jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(const string&, R (CT::*)(ArgsT ...) const, Extra ...) [with R = R; CT = CT; ArgsT = {ArgsT ...}; Extra = {Extra ...}; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1091 |   TypeWrapper<T>& method(const std::string& name, R(CT::*f)(ArgsT...) const, Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1091:19: note:   template argument deduction/substitution failed:
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:19:23: note:   mismatched types ‘R (CT::*)(ArgsT ...) const’ and ‘uint32_t (*)()’ {aka ‘unsigned int (*)()’}
   19 |         wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/kholod/libcxxwrap-julia/install/include/jlcxx/jlcxx.hpp:15,
                 from /home/kholod/openfhe-julia/src/privatekeyimpl.cpp:1:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1101:19: note: candidate: ‘template<class LambdaT, class ... Extra, typename std::enable_if<(jlcxx::detail::has_call_operator<LambdaT>::value && (! std::is_member_function_pointer<_Tp>::value)), bool>::type <anonymous> > jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(const string&, LambdaT&&, Extra ...) [with LambdaT = LambdaT; Extra = {Extra ...}; typename std::enable_if<(jlcxx::detail::has_call_operator<LambdaT>::value && (! std::is_member_function_pointer<LambdaT>::value)), bool>::type <anonymous> = <anonymous>; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1101 |   TypeWrapper<T>& method(const std::string& name, LambdaT&& lambda, Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1101:19: note:   template argument deduction/substitution failed:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1100:132: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
 1100 | _t<detail::has_call_operator<LambdaT>::value && !std::is_member_function_pointer<LambdaT>::value, bool> = true>
      |                                                                                                           ^~~~

/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1110:19: note: candidate: ‘template<class R, class CT, class ... ArgsT, class ... Extra> jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(R (CT::*)(ArgsT ...), Extra ...) [with R = R; CT = CT; ArgsT = {ArgsT ...}; Extra = {Extra ...}; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1110 |   TypeWrapper<T>& method(R(CT::*f)(ArgsT...), Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1110:19: note:   template argument deduction/substitution failed:
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:19:23: note:   mismatched types ‘R (CT::*)(ArgsT ...)’ and ‘const char*’
   19 |         wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/kholod/libcxxwrap-julia/install/include/jlcxx/jlcxx.hpp:15,
                 from /home/kholod/openfhe-julia/src/privatekeyimpl.cpp:1:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1117:19: note: candidate: ‘template<class R, class CT, class ... ArgsT, class ... Extra> jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(R (CT::*)(ArgsT ...) const, Extra ...) [with R = R; CT = CT; ArgsT = {ArgsT ...}; Extra = {Extra ...}; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1117 |   TypeWrapper<T>& method(R(CT::*f)(ArgsT...) const, Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1117:19: note:   template argument deduction/substitution failed:
/home/kholod/openfhe-julia/src/privatekeyimpl.cpp:19:23: note:   mismatched types ‘R (CT::*)(ArgsT ...) const’ and ‘const char*’
   19 |         wrapped.method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);
      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/kholod/libcxxwrap-julia/install/include/jlcxx/jlcxx.hpp:15,
                 from /home/kholod/openfhe-julia/src/privatekeyimpl.cpp:1:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1127:19: note: candidate: ‘template<class LambdaT, class ... Extra, typename std::enable_if<jlcxx::detail::has_call_operator<LambdaT>::value, bool>::type <anonymous> > jlcxx::TypeWrapper<T>& jlcxx::TypeWrapper<T>::method(LambdaT&&, Extra ...) [with LambdaT = LambdaT; Extra = {Extra ...}; typename std::enable_if<jlcxx::detail::has_call_operator<LambdaT>::value, bool>::type <anonymous> = <anonymous>; T = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > >]’
 1127 |   TypeWrapper<T>& method(LambdaT&& lambda, Extra... extra)
      |                   ^~~~~~
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1127:19: note:   template argument deduction/substitution failed:
/home/kholod/libcxxwrap-julia/install/include/jlcxx/module.hpp:1126:80: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
 1126 |            std::enable_if_t<detail::has_call_operator<LambdaT>::value, bool> = true>
      |                                                                                ^~~~
make[2]: *** [CMakeFiles/openfhe_julia.dir/build.make:219: CMakeFiles/openfhe_julia.dir/src/privatekeyimpl.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/openfhe_julia.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
barche commented 7 months ago

I'm not sure why this worked before, but for static methods you should use something like this (note the extra module()) :

wrapped.module().method("PrivateKeyImpl__SerializedVersion", &WrappedT::SerializedVersion);

Otherwise, it is assumed that a member function is wrapped. Since that is not the case here, none of the methods for adding a member function match, because the function pointer type is different, resulting in a quite verbose error here.

ArseniyKholod commented 7 months ago

Thanks! It works now!!!

sloede commented 7 months ago

@barche I truly appreciate you taking the time to help us out - thank you very much for your support!