Skip to content

Commit cd56bf0

Browse files
authored
Add extra inheritance example (#480)
* Add extra inheritance example Ref: JuliaPackaging/Yggdrasil#10818 * Use a closure as callback, accessing class data * Make inheritance test work on platforms that don't support cfunctions on closures
1 parent 74a4641 commit cd56bf0

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

test/inheritance.jl

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
include(joinpath(@__DIR__, "testcommon.jl"))
22

3+
GC.enable(true)
4+
35
# Wrap the functions defined in C++
46
module CppInheritance
57

@@ -25,6 +27,47 @@ end
2527

2628
using .CppInheritance
2729

30+
# Normal Julia callback
31+
function double(x::Float64)
32+
return 2x
33+
end
34+
35+
# callback as a C function
36+
c_double = @safe_cfunction(double, Float64, (Float64,))
37+
38+
# Base class for extended classes in Julia
39+
abstract type AbstractJuliaExtended <: CppInheritance.VirtualCpp end
40+
# Every C++ function called on the Julia extended classes needs this kind of specialization
41+
CppInheritance.virtualfunc(x::AbstractJuliaExtended) = CppInheritance.virtualfunc(x.referred_object)
42+
43+
function make_callback(firstval_ref)
44+
cb(x::Float64) = 2x + firstval_ref[]
45+
cb_noclosure(x::Float64) = 3x
46+
try
47+
return @safe_cfunction($cb, Float64, (Float64,))
48+
catch e
49+
@warn "Creating cfunction failed with error $e"
50+
return @safe_cfunction($cb_noclosure, Float64, (Float64,))
51+
end
52+
end
53+
54+
# Example of an extension implemented in Julia
55+
struct JuliaExtended <: AbstractJuliaExtended
56+
function JuliaExtended(len, value)
57+
ref_obj = CppInheritance.VirtualCfunctionExtended(len,value)
58+
59+
# Get a reference in case the value changes
60+
firstval_ref = CxxWrap.StdLib.cxxgetindex(CppInheritance.getData(ref_obj), 1)
61+
62+
c_cb = make_callback(firstval_ref)
63+
64+
CppInheritance.set_callback(ref_obj, c_cb)
65+
return new(ref_obj, c_cb)
66+
end
67+
referred_object::CppInheritance.VirtualCfunctionExtended
68+
callback::CxxWrap.SafeCFunction # Needed to avoid garbage collection of the function
69+
end
70+
2871
@testset "$(basename(@__FILE__)[1:end-3])" begin
2972

3073
b = B()
@@ -76,4 +119,23 @@ VirtualSolver.solve(a)
76119
b = VirtualSolver.F(@safe_cfunction(x -> 2x, Float64, (Float64,)))
77120
VirtualSolver.solve(b)
78121

79-
end
122+
let virt_extended_julia = CppInheritance.VirtualCppJuliaExtended(100000,1.0)
123+
CppInheritance.set_callback(virt_extended_julia, double)
124+
@test CppInheritance.virtualfunc(virt_extended_julia) == 200000
125+
@time CppInheritance.virtualfunc(virt_extended_julia)
126+
end
127+
128+
let virt_extended_julia = CppInheritance.VirtualCfunctionExtended(100000,2.0)
129+
CppInheritance.set_callback(virt_extended_julia, c_double)
130+
@test CppInheritance.virtualfunc(virt_extended_julia) == 400000
131+
@time CppInheritance.virtualfunc(virt_extended_julia)
132+
end
133+
134+
let virt_extended_julia = JuliaExtended(100000, 4.0)
135+
@test CppInheritance.virtualfunc(virt_extended_julia) == 1200000
136+
GC.gc()
137+
@time CppInheritance.virtualfunc(virt_extended_julia)
138+
end
139+
140+
end
141+

0 commit comments

Comments
 (0)