With restrictions
In the previous section we've seen that we can derive OpaqueType
for types with generics. There's a limitation, though: if a generic of the type is bounded by a trait which isn't implemented for ()
, deriving the trait will fail.
Every opaque type has an associated Key
type, which must be unique and the same for the entire family of types (i.e. it must not depend on any of the generics). It's normally generated by replacing all generics with ()
. We have to provide a custom Key
if this default type is rejected due to bounds on the type, it can be set with the #[jlrs(key = "path::to::Type")]
attribute. The key type must implement Any
. In practice, it's best to use one of the exported variants or a custom zero-sized type.
use std::fmt::Debug;
use jlrs::{
data::{
managed::{ccall_ref::CCallRefRet, value::typed::TypedValue},
types::construct_type::ConstructType,
},
prelude::*,
weak_handle,
};
pub trait IsFloat {}
impl IsFloat for f32 {}
impl IsFloat for f64 {}
#[derive(Debug, OpaqueType)]
#[jlrs(key = "Opaque<f64>")]
struct Opaque<T: IsFloat> {
_a: T,
}
impl<T: 'static + Send + Sync + ConstructType + Debug + IsFloat> Opaque<T> {
fn new(a: T) -> CCallRefRet<Opaque<T>> {
match weak_handle!() {
Ok(handle) => CCallRefRet::new(TypedValue::new(handle, Opaque { _a: a }).leak()),
Err(_) => panic!("not called from Julia"),
}
}
fn print(&self) {
println!("{:?}", self)
}
}
julia_module! {
become julia_module_tutorial_init_fn;
for T in [f32, f64] {
struct Opaque<T>;
in Opaque<T> fn new(a: T) -> CCallRefRet<Opaque<T>> as Opaque;
in Opaque<T> fn print(&self);
};
type OpaqueF32 = Opaque<f32>;
in Opaque<f32> fn new(a: f32) -> CCallRefRet<Opaque<f32>> as OpaqueF32;
}
julia> module JuliaModuleTutorial ... end
Main.JuliaModuleTutorial
julia> v = JuliaModuleTutorial.Opaque(Float32(3.0))
Main.JuliaModuleTutorial.Opaque{Float32}()
julia> v = JuliaModuleTutorial.Opaque(Float64(3.0))
Main.JuliaModuleTutorial.Opaque{Float64}()
julia> v = JuliaModuleTutorial.OpaqueF32(Float32(3.0))
Main.JuliaModuleTutorial.Opaque{Float32}()
julia> JuliaModuleTutorial.print(v)
Opaque { _a: 3.0 }