JuliaInterop / CxxWrap.jl

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

Double registration error #422

Closed claud10cv closed 6 months ago

claud10cv commented 6 months ago

I am writing a Julia package to provide simple entry points to two C++ codes. In each of the two C++ codes (say codes A and B providing shared libraries libA.so and libB.so) I have written CxxWrap functions as follows:

For library libA.so:

#include "jlcxx/jlcxx.hpp"

static void A(jlcxx::ArrayRef<int> _src, jlcxx::ArrayRef<int> _dst, jlcxx::ArrayRef<int> _sol);
JLCXX_MODULE define_julia_module(jlcxx::Module& mod);

For library libB.so

#include "jlcxx/jlcxx.hpp"

static void B(jlcxx::ArrayRef<int> _src, jlcxx::ArrayRef<int> _dst, jlcxx::ArrayRef<int> _sol);
JLCXX_MODULE define_julia_module(jlcxx::Module& mod);

Both libraries are built using BinaryBuilder and wrapped into Julia Packages LibA_jll.jl and LibB_jll.jl.

Both function names are different, but they share the same types of arguments and the same return type. In Julia, I am trying to expose functions A and B from these two libs as follows:

module WrapperAB
    using CxxWrap
    using LibA_jll
    using LibB_jll

    @wrapmodule () -> joinpath("", "libA")
    @wrapmodule () -> joinpath("", "libB") # line WrapperAB.jl:14, see below
end

This code triggers the following error when trying to precompile the module WrapperAB:

ERROR: LoadError: Double registration for method (:function, :A, :WrapperAB, 0xd4a10266d64cfd0d): A; Any[Vector{Int32}, Vector{Int32}, Vector{Int32}]; Nothing
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] _register_function_pointers(func::CxxWrap.CxxWrapCore.CppFunctionInfo, precompiling::Bool)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/HG6cm/src/CxxWrap.jl:388
 [3] wrap_functions(functions::Vector{CxxWrap.CxxWrapCore.CppFunctionInfo}, julia_mod::Module)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/HG6cm/src/CxxWrap.jl:763
 [4] wrapfunctions(jlmod::Module)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/HG6cm/src/CxxWrap.jl:785
 [5] wrapmodule(so_path_cb::Function, funcname::Symbol, m::Module, flags::Nothing)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/HG6cm/src/CxxWrap.jl:822
 [6] top-level scope
   @ ~/git/WrapperAB.jl/src/WrapperAB.jl:14

It seems as if functions A and B were treated as being the same and the wrapper were unable to differentiate between the two.

claud10cv commented 6 months ago

As stupid as it may seem, the solution was quite simple. It involves encapsulating the cxx part in the module WrapperAB, as follows


module WrapperAB

    module A
        using CxxWrap
        using LibA_jll
        @wrapmodule () -> joinpath("", "libA")
        function __init__()
            @initcxx
        end
    end 

    module B
        using CxxWrap
        using LibB_jll
        @wrapmodule () -> joinpath("", "libB")
        function __init__()
            @initcxx
        end
    end 

end