julia --project -e 'using Pkg; Pkg.instantiate()'
julia --project configure.jl
make -C build
julia --project wrap.jl
Last active
August 12, 2021 12:40
-
-
Save maleadt/e47d7d88ebdd5f938ba8aebd3662646f to your computer and use it in GitHub Desktop.
CxxWrap pointer MWE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
build | |
Manifest.toml |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.13) | |
set(CMAKE_CXX_STANDARD 17) | |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | |
project(wrap) | |
find_package(JlCxx) | |
add_library(wrap SHARED wrap.cpp) | |
target_link_libraries(wrap | |
JlCxx::cxxwrap_julia | |
) | |
install(TARGETS wrap | |
LIBRARY DESTINATION lib) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using CxxWrap | |
prefix = String[] | |
push!(prefix, dirname(Base.julia_cmd()[1])) | |
push!(prefix, CxxWrap.prefix_path()) | |
run(`cmake -S $(@__DIR__) -B $(joinpath(@__DIR__, "build")) -DCMAKE_PREFIX_PATH=$(join(prefix, ';'))`) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[deps] | |
CxxWrap = "1f15a43c-97ca-5a2a-ae31-89f07a497df4" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <jlcxx/jlcxx.hpp> | |
#include <iostream> | |
template <typename T> struct MyCxxPtr { | |
typedef T value_type; | |
MyCxxPtr(T *ptr) : m_ptr(ptr) {} | |
// implicit conversion to a regular pointer | |
operator T *() const { return m_ptr; } | |
T *m_ptr; | |
}; | |
void printit(float* a) { | |
std::cout << a << std::endl; | |
} | |
void foobar(MyCxxPtr<float> a) { printit(a); } | |
JLCXX_MODULE define_module(jlcxx::Module &mod) { | |
using namespace jlcxx; | |
// TODO: map_type directly to MyPtr? | |
mod.add_type<Parametric<TypeVar<1>>>("MyCxxPtr") | |
.apply<MyCxxPtr<float>>([](auto wrapped) { | |
typedef typename decltype(wrapped)::type WrappedT; | |
wrapped.template constructor<typename WrappedT::value_type*>(); | |
}); | |
mod.method("foobar", foobar); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using CxxWrap | |
# what I have: a custom primitive pointer type, and an array using it | |
primitive type MyPtr{T} 64 end | |
Base.cconvert(::Type{<:MyPtr}, x) = x | |
struct MyArray{T} | |
ptr::MyPtr{T} | |
end | |
Base.unsafe_convert(::Type{MyPtr{T}}, a::MyArray{T}) where {T} = a.ptr | |
# what I want: to pass a MyArray directly to a ccall with MyPtr, because that | |
# performs the necessary conversions automatically (keeping the array alive) | |
x = MyArray{Float32}(reinterpret(MyPtr{Float32}, Int(0xdeadbeef))) | |
# what ccall does: | |
@assert Base.unsafe_convert(MyPtr{Float32}, Base.cconvert(MyPtr{Float32}, x)) == x.ptr | |
# XXX: currently it seems impossible to `map_type` the parametric MyPtr directly, | |
# so we'll be using a MyCxxPtr as defined by CxxWrap's add_type and forward calls. | |
# this assumes that the layout of MyPtr is the same as the layout of MyCxxPtr. | |
# @wrapmodule(joinpath(@__DIR__, "build/libwrap.so"), :define_module) | |
@readmodule(joinpath(@__DIR__, "build/libwrap.so"), :define_module) | |
@wraptypes | |
# XXX: need to use <: MyCxxPtr because the actual values are MyCxxPtrAllocated <: MyCxxPtr | |
CxxWrap.argument_overloads(t::Type{<:MyCxxPtr{T}}) where {T} = [MyArray{T}] | |
@wrapfunctions | |
# forward calls | |
Base.cconvert(::Type{<:MyCxxPtr}, x) = x | |
Base.unsafe_convert(::Type{<:MyCxxPtr{T}}, ::MyArray{T}) where {T} = | |
MyCxxPtr{T}(reinterpret(Ptr{T}, Base.unsafe_convert(MyPtr{T}, x))) | |
## demo | |
# passing the C++-version of a pointer works as expected | |
foobar(MyCxxPtr{Float32}(C_NULL)) | |
# passing an array doesn't, despite the `argument_overloads` above | |
# using InteractiveUtils | |
# @code_warntype foobar(x) | |
foobar(x) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment