Skip to content

Instantly share code, notes, and snippets.

@Clemapfel
Last active March 14, 2022 20:40
Show Gist options
  • Save Clemapfel/47906ecb28f2681b6a6759b5bb663943 to your computer and use it in GitHub Desktop.
Save Clemapfel/47906ecb28f2681b6a6759b5bb663943 to your computer and use it in GitHub Desktop.
//
// Copyright 2022 Clemens Cords
// Created on 14.03.22 by clem (mail@clemens-cords.com)
//
#include <jluna.hpp>
using namespace jluna;
// this code are examples given as a response to https://github.com/Clemapfel/jluna/issues/12
int main()
{
State::initialize();
// first, we allocate an array julia-side
// State::safe_eval automatically creates a proxy that manages the julia-side memory
// this will make it be safe from the garbage collector (GC)
auto julia_side_array_proxy = State::safe_eval(R"(
julia_side_array = [Float32(i) for i in 1:100000]
return julia_side_array
)");
// ### Method 1: Using jluna::Array (recommended)
{
Array<Float32, 1> as_array = julia_side_array_proxy; // causes no reallocation
// accessing values
std::cout << (Float32) as_array.at(10) << std::endl;
// changing values
as_array.at(10) = 1234;
State::safe_eval("println(julia_side_array[11])"); // julia indices are 1-based
as_array.at(10) = 11;
// accessing raw c-data of the array
Float32* c_array = (Float32*) as_array.data();
std::cout << c_array[10] << std::endl;
// converting an array iterator to a raw c-pointer
auto it = as_array.at(10);
Any* as_ptr = (Any*) it;
std::cout << *((Float32*) as_ptr) << std::endl;
}
std::cout << "\n---\n" << std::endl;
// ### Method 2: Using non-jluna Julia Functions (works for any objects, not just arrays)
{
auto getindex = Base["getindex"];
auto setindex = Base["setindex!"];
// accessing values
std::cout << (Float32) getindex(julia_side_array_proxy, 10 + 1) << std::endl;
// changing values
setindex(julia_side_array_proxy, 1234, 10 + 1);
State::safe_eval("println(julia_side_array[11])");
setindex(julia_side_array_proxy, 11, 10 + 1);
}
std::cout << "\n---\n" << std::endl;
// ### Method 2.5: Using non-jluna julia functions with less nice syntax but no overhead
{
// create a garbage collector sentinel that protects any values that are inside this block
auto sentinel = GCSentinel();
auto* getindex = jl_find_function("Base", "getindex");
auto* setindex = jl_find_function("Base", "setindex!");
// accessing values
Any* result = jluna::call(getindex, (Any*) julia_side_array_proxy, box<Int64>(10 + 1));
std::cout << unbox<Float32>(result) << std::endl;
// changing values
jluna::call(setindex, (Any*) julia_side_array_proxy, box<Float32>(1234), box<Int64>(10 + 1));
State::safe_eval("println(julia_side_array[11])");
jluna::call(setindex, (Any*) julia_side_array_proxy, box<Float32>(11), box<Int64>(10 + 1));
// because the block ends here, sentinel is destroyed and releases any values protected
}
std::cout << "\n---\n" << std::endl;
// ### Method 3: Using the C-API (also no overhead, same speed as Method 2.5)
{
// first, disable gc
jl_gc_enable(false);
// get a C-API array pointer to proxies value
jl_array_t* as_array = (jl_array_t*) ((Any*) julia_side_array_proxy);
// accessing values
std::cout << jl_unbox_float32(jl_arrayref(as_array, 10)) << std::endl;
// changing values
jl_arrayset(as_array, jl_box_float32(1234.0), 10);
State::safe_eval("println(julia_side_array[11])");
jl_arrayset(as_array, jl_box_float32(11.0), 10);
// reenable gc
jl_gc_enable(true);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment