# CxxWrap std::vector\<T\> as a function argument

**URL:** <https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694>\
**Category:** New to Julia\
**Tags:** cxx\
**Created:** [October 26, 2017, 8:14am UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694 "2017-10-26T08:14:39Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![igor.cerovsky](https://avatars.discourse-cdn.com/v4/letter/i/c37758/32.png) [@igor.cerovsky](https://discourse.julialang.org/u/igor.cerovsky)\
**Post date:** [October 26, 2017, 8:14am UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/1 "2017-10-26T08:14:39Z")

</div>

Hello, is there a simple/built in way to pass array of C++ stucts from Julia to c++?

C++ code:

```julia
struct Foo
{
  std::wstring name;
  int dataLen;
  double* data;
};

void useFooVec(const std::vector<Foo>& v) # how to deal with the vector<T> to be called from julia?
{
  // ...
}

```

Julia side

```julia
using CxxWrap

wrap_modules(raw"PATH_TO_MODULE\foo.dll")

struct JFoo
  name::String
  data::Vector{Float64}
end

jFooVec = [JFoo("a", [1., 2., 3.]), JFoo("b", [11., 12., 13.])]

# CppFoo.useFooVec(jFooVec) # ???

```

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [October 26, 2017, 1:48pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/2 "2017-10-26T13:48:03Z")

</div>

```julia
struct CFoo
  name::Ptr{Cwchar_t}
  len::Cint 
  data::Ptr{Float64}
end
struct JFoo
  name::String
  data::Vector{Float64}
end

function Base.cconvert(x::JFoo)
     # Might work a bit simpler, but for all I know this is the official way that makes sure we preserve gc roots!
    nptr = Base.unsafe_convert(Ptr{Cwchar_t}, Base.cconvert(Cwstring, x.name))
    dptr = Base.unsafe_convert(Ptr{Float64}, Base.cconvert(Ptr{Float64}, x.data))
    CFoo(nptr, Cint(length(x.data)), dptr)
end

```

I think that’s what you need to do… Sorry for the awkwardness, I think cstruct compatibility needs a revamp 😉  
_edit_  
you might also want to see the ccall signature

```julia
j_interact_with_struct(x::JFoo) = ccall((:c_interact_with_struct, lib), Void, Tuple{CFoo}, x)

```

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [October 26, 2017, 9:32pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/3 "2017-10-26T21:32:54Z")

</div>

If you can modify the type on the C++ side to add a constructor, and if you don’t need a “mirror” struct on the Julia side, this would be the current way to do it in CxxWrap:

C++:

```cpp

struct Foo
{
  Foo(const std::wstring& n, jlcxx::ArrayRef<double,1> d) : name(n), data(d.begin(), d.end())
  {
  }

  std::wstring name;
  std::vector<double> data;
};

// In the module definition
foomod.add_type<Foo>("Foo")
  .constructor<const std::wstring&, jlcxx::ArrayRef<double,1>>()
  .method("name", [](Foo& f) { return f.name; })
  .method("data", [](Foo& f) { return jlcxx::ArrayRef<double,1>(&(f.data[0]), f.data.size()); });

foomod.method("print_foo_array", [] (jlcxx::ArrayRef<jl_value_t*> farr)
{
  for(jl_value_t* v : farr)
  {
    const Foo& f = *jlcxx::unbox_wrapped_ptr<Foo>(v);
    std::wcout << f.name << ":";
    for(const double d : f.data)
    {
      std::wcout << " " << d;
    }
    std::wcout << std::endl;
  }
});

```

Julia side:

```julia
using CxxWrap
wrap_modules(raw"PATH_TO_MODULE\foo.dll")
using FooMod: Foo, name, data, print_foo_array

foovec = Any[Foo("a", [1.0, 2.0, 3.0]), Foo("b", [11.0, 12.0, 13.0])] # Must be Any because of the boxing
@show name(foovec[1])
@show data(foovec[1])
print_foo_array(foovec)

```

This approach is not ideal:

- The structs are boxed, so you have an array of pointers. To pack the data, you have to use @sdanisch 's approach with an intermediate `isbits` struct
- Currently `std::vector` is not wrapped, so if you need that in your API it will need extra work
- ArrayRef doesn’t support boxed values directly, so you need the `jl_value_t*` and `unbox_wrapped_ptr` ugliness.

---

<div class="post-metadata">

**Author:** ![igor.cerovsky](https://avatars.discourse-cdn.com/v4/letter/i/c37758/32.png) [@igor.cerovsky](https://discourse.julialang.org/u/igor.cerovsky)\
**Post date:** [October 26, 2017, 10:05pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/4 "2017-10-26T22:05:37Z")

</div>

barche, thanks a lot 🙂  
I’ve been approaching your solution slowly… I’ve modified Foo on the C++ side, but the approach with the data copying looks much better.

```julia
struct Foo
{
  Foo(const std::wstring name, jlcxx::ArrayRef<double> data) : 
    _name{ name }, _data{data} {}
  std::wstring _name;
  jlcxx::ArrayRef<double> _data;
};

```

And the trick with `print_foo_array... `👍  
Despite the not wrapped `std::vector` and the boxed ugliness, the solution looks great.  
Could you please explain, what work is needed to wrap the `std::vector`?

Thanks to everyone who is supporting C++ usage with Julia, great work guys!

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [October 27, 2017, 9:36am UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/5 "2017-10-27T09:36:33Z")

</div>

OK, great! Note that `ArrayRef` does not protect the referenced array from garbage collection, so the array should be referenced explicitly on the Julia side if you keep an `ArrayRef` stored somewhere.

Regarding `std::vector`, I think that something like what I’m doing for the [Trilinos Kokkos View](https://trilinos.org/docs/dev/packages/kokkos/doc/html/classKokkos_1_1View.html) should work. The idea is that you get a pointer to the C++ data, which is wrapped in a Julia type that implements the Array interface. To be completely general, for element types that are non-bits the actual vector should be wrapped and accessed using `std::vector` access functions, instead of using the raw data pointer. The C++ code:  
[https://github.com/barche/Trilinos.jl/blob/master/deps/src/trilinoswrap/kokkos.cpp](https://github.com/barche/Trilinos.jl/blob/master/deps/src/trilinoswrap/kokkos.cpp)

Julia code:  
[https://github.com/barche/Trilinos.jl/blob/master/src/Kokkos.jl](https://github.com/barche/Trilinos.jl/blob/master/src/Kokkos.jl)

---

<div class="post-metadata">

**Author:** ![igor.cerovsky](https://avatars.discourse-cdn.com/v4/letter/i/c37758/32.png) [@igor.cerovsky](https://discourse.julialang.org/u/igor.cerovsky)\
**Post date:** [October 28, 2017, 8:25pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/6 "2017-10-28T20:25:32Z")

</div>

Thanks, for the note. Your solution looks better, I like the constructor trick.

Regarding the `std::vector`,the way seems to be clear. Thanks for help!

---

<div class="post-metadata">

**Author:** ![igor.cerovsky](https://avatars.discourse-cdn.com/v4/letter/i/c37758/32.png) [@igor.cerovsky](https://discourse.julialang.org/u/igor.cerovsky)\
**Post date:** [November 6, 2017, 7:42am UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/7 "2017-11-06T07:42:02Z")

</div>

One more question: Is there a way to call a callback defined in Julia where input parameter is `Vector`?

```julia
function testf_arf(v::Vector{Float64}, s::String)
  r = sum(v)
  print_with_color(:green, "callback in Julia: $(s) = $(r)\n")
  return r
end

@show c_func_arf = safe_cfunction(testf_arf, Float64, (CxxWrap.CppArray{Float64}, String))

```

C++ side:

```julia
foomod.method("fn_clb", [](double(*fnClb)(jlcxx::ArrayRef<double>, wstring))
{
  vector<double> v{ 1., 2. };
  auto ar = jlcxx::ArrayRef<double, 1>(v.data(), v.size());
  // fnClb(ar.wrapped(), L"calledFromCPP"); // ??? 
});

```

---

<div class="post-metadata">

**Author:** ![igor.cerovsky](https://avatars.discourse-cdn.com/v4/letter/i/c37758/32.png) [@igor.cerovsky](https://discourse.julialang.org/u/igor.cerovsky)\
**Post date:** [November 6, 2017, 2:16pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/8 "2017-11-06T14:16:15Z")

</div>

I’m using Julia 0.6 and the `Base.cconvert` generates an error, and that was the reason I was preferring the CxxWrap solution.

```julia
julia> Base.cconvert(CFoo, jFoo)
ERROR: MethodError: Cannot `convert` an object of type JFoo to an object of type CFoo
This may have arisen from a call to the constructor CFoo(...),
since type constructors fall back to convert methods.
Stacktrace:
 [1] cconvert(::Type{T} where T, ::JFoo) at .\essentials.jl:149

```

the problem can be overcome by writing a constructor for `CFoo`, which works fine:

```julia
struct CFoo
  name::Ptr{Cwchar_t}
  len::Cint 
  data::Ptr{Float64}

  function CFoo(a::JFoo)
    dptr = Base.unsafe_convert(Ptr{Float64}, Base.cconvert(Ptr{Float64}, a.data))
    nptr = Base.unsafe_convert(Ptr{Cwchar_t}, Base.cconvert(Cwstring, a.name))
    new(nptr, Cint(length(a.data)), dptr)
  end
end

jFooVec = [JFoo("a", [1., 2., 3.]), JFoo("b", [11., 12., 13.])]
cFooVec = [CFoo(a) for a in jFooVec]

```

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [November 8, 2017, 4:26pm UTC](https://discourse.julialang.org/t/cxxwrap-std-vector-t-as-a-function-argument/6694/9 "2017-11-08T16:26:28Z")

</div>

> [@igor.cerovsky](#):
>
> One more question: Is there a way to call a callback defined in Julia where input parameter is Vector

Yes, but here too the parameters (both string and vector) need to be boxed:

```c++
mod.method("fn_clb", [](double (*fnClb)(jl_value_t*, jl_value_t*)) {
    std::vector<double> v{1., 2.};
    auto ar = jlcxx::ArrayRef<double, 1>(v.data(), v.size());
    fnClb((jl_value_t *)ar.wrapped(), jlcxx::box(std::wstring(L"calledFromCPP")));
});

```

And then in Julia the cfunction signature must use `Any`:

```julia
c_func_arf = safe_cfunction(testf_arf, Float64, (Any,Any))
fn_clb(c_func_arf)

```

It’s also possible to directly use the regular Julia function:

```c++
mod.method("fn_clb2", [] (jl_function_t* f) {
    std::vector<double> v{1., 2.};
    auto ar = jlcxx::ArrayRef<double, 1>(v.data(), v.size());
    jlcxx::JuliaFunction fnClb(f);
    fnClb((jl_value_t*)ar.wrapped(), std::wstring(L"calledFromCPP"));
});

```

Then in Julia you just need:

```julia
fn_clb2(testf_arf)

```

BTW, if this needs to be elaborated further it may be better to create an issue on the CxxWrap github.
