Convert vector Cxx to Julia vector
julia> using Cxx
julia> cxx""" #include <vector> """
true
julia> cxx""" std::vector<int> a = std::vector<int> (5,6); """
true
julia> icxx""" a[0]; """
(int &) 6
julia> b = icxx""" a; """
(class std::vector<int, class std::allocator<int> >) {
}
julia> b[0]
6
julia> b
(class std::vector<int, class std::allocator<int> >) {
}
The above code, when entered into the Julia terminal, shows that there is vector data. However, I would prefer to completely move it to the Julia array. What's the best way to do this?
Note. In the end, the shared library will return std::vector<int>
, so the question, more specifically, is how best to convert std::vector<int>
to a standard Julia vector. (This refers to the variable b
in the example code).
Thanks in advance.
EDIT: The reason why the problem occurs seems unclear, so hopefully the following will help (it follows directly from the code above)
julia> unsafe_wrap(Array, pointer(b), length(b))
ERROR: MethodError: objects of type Ptr{Int32} are not callable
julia> @cxx b;
ERROR: Could not find `b` in translation unit
julia> cxx" b; "
In file included from :1:
__cxxjl_17.cpp:1:2: error: C++ requires a type specifier for all declarations
b;
^
true
julia> icxx" b; "
ERROR: A failure occured while parsing the function body
julia> cxx" &b; "
In file included from :1:
__cxxjl_15.cpp:1:3: error: C++ requires a type specifier for all declarations
&b;
^
__cxxjl_15.cpp:1:3: error: declaration of reference variable 'b' requires an initializer
&b;
^
true
julia> icxx" &b; "
ERROR: A failure occured while parsing the function body
julia> @cxx &b;
LLVM ERROR: Program used external function 'b' which could not be resolved!
Regardless of how you try to pass the julia reference variable, it cannot be parsed back into the C ++ environment (and the latter completely ruined julia). You cannot use the same methods as for using C ++ references in julia. Trying to capture the pointer or the b
, @b
, b[0]
, or &b[0]
and dismantle these works.
source to share
Thanks to Jeff Besancon and Isaiah for their answers ( icxx" &a[0]; "
and sum = icxx""" std::accumulate($b.begin(), $b.end(), 0); """
accordingly)
To put everything together in one answer, I made the following example:
# Converting between Julia and C++
using Cxx
cxxinclude("vector")
cxx" std::vector<int> a = std::vector<int> (5,6); "
# Transfer variable from C++ space to julia space "as is"
b = @cxx a;
# Pass the raw data reference from the C++ variable into julia space
c = icxx" &a[0]; " # From C++ space
d = icxx" &$b[0]; " # From julia space, only difference is the '$' interpolation
# Get the number of elements in the vector
cSize = icxx" a.size(); "
dSize = icxx" $b.size(); "
# Convert to a standard julia array
juliaArray_c = unsafe_wrap(Array, c, cSize, true)
juliaArray_d = unsafe_wrap(Array, d, dSize, true).
Hope this helps others who are in the same situation.
source to share
The question here is still not clear, but when answering the change: pass the CppValue
Julia variable back to icxx
, use interpolation. For example:
julia> cxx""" std::vector<int> a = std::vector<int> (5,6); """
true
julia> b = @cxx a
(class std::__1::vector<int, class std::__1::allocator<int> >) {
}
julia> typeof(b)
Cxx.CppValue{Cxx.CxxQualType{Cxx.CppTemplate{Cxx.CppBaseType{Symbol("std::__1::vector")},Tuple{Int32,Cxx.CxxQualType{Cxx.CppTemplate{Cxx.CppBaseType{Symbol("std::__1::allocator")},Tuple{Int32}},(false, false, false)}}},(false, false, false)},24}
julia> cxxinclude("numeric")
julia> sum = icxx""" std::accumulate($b.begin(), $b.end(), 0); """
30
As far as "spaces" are concerned, I don't believe Example 8 or the docs at all constitute a normative variable declaration statement, but in general Julia references might be more convenient to use with Julia code. The examples given in Jeff's answer are the solution to make a shell without a copy. For working with data declared as std::vector
, the options I know of are: copy, wrap the pointer, or use the provided overloads getindex
to handle the data as a Julia array (0 based) (which makes the pointer-scope automatically and shouldn't have any overhead costs).
source to share