# Example of registering a finalizer for unsafe\_wrapped data from ccall

**URL:** <https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499>\
**Category:** New to Julia\
**Tags:** ccall, finalization\
**Created:** [November 11, 2024, 2:49pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499 "2024-11-11T14:49:37Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![gmcardle](https://avatars.discourse-cdn.com/v4/letter/g/34f0e0/32.png) [@gmcardle](https://discourse.julialang.org/u/gmcardle)\
**Post date:** [November 11, 2024, 2:49pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/1 "2024-11-11T14:49:37Z")

</div>

Hi, I’m using `ccall` on a C library that returns a pointer to some data that was malloced in the library and requires a separate API call to close the resource that the data came from. The dataset could be quite large (a couple of GB) so I’d rather use unsafe\_wrap in julia, but I’m not familiar with how to implement finalizers. The julia docs imply that a finalizer can only be registered for a mutable struct. Here’s a fictional gist of my application:

```julia
function getCdata(recordNum::Integer)
    handle = @ccall mylib.openRecord(recordNum::Cint)::Cint
    if handle < 0
        error("failed to open record ", recordNum)
    end
    leng = @ccall mylib.getRecordSize(handle::Cint)::Cint
    dataPtr = @ccall mylib.getRecordData(handle::Cint)::Ptr{UInt8}
    dataRef = unsafe_wrap(Array, dataPtr, leng)
    closefunc() = @ccall mylib.closeRecord(handle::Cint)::Cvoid
    return (dataRef,closefunc)
end

```

So the function opens a record via the c library and wraps the array in `dataRef`. It also returns a closure that can call the api close function, but how do I arrange that the garbage collector will call this (or do something to the same effect) when I’m done using `dataRef`?

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [November 11, 2024, 3:14pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/2 "2024-11-11T15:14:16Z")

</div>

Should be

```julia
return finalizer(dataRef) do ref
   closefunc()
end

```

---

<div class="post-metadata">

**Author:** ![gmcardle](https://avatars.discourse-cdn.com/v4/letter/g/34f0e0/32.png) [@gmcardle](https://discourse.julialang.org/u/gmcardle)\
**Post date:** [November 12, 2024, 10:15am UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/3 "2024-11-12T10:15:20Z")

</div>

Wow, thanks, that was simpler than expected. So do you know if I need the closure function at all or can I use the `do` block for this directly, i.e.

```julia
return finalizer(dataRef) do
    @ccall mylib.closeRecord(handle::Cint)::Cvoid
end

```

or would the `handle` go out of context?

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [November 12, 2024, 10:16am UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/4 "2024-11-12T10:16:49Z")

</div>

I think that’s fine.

---

<div class="post-metadata">

**Author:** ![gmcardle](https://avatars.discourse-cdn.com/v4/letter/g/34f0e0/32.png) [@gmcardle](https://discourse.julialang.org/u/gmcardle)\
**Post date:** [November 12, 2024, 10:37am UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/5 "2024-11-12T10:37:51Z")

</div>

OK thanks again. Well, it looks like the finalizer was registered but threw an error on julia exit. Not sure if it’s me or a julia bug.

> error in running finalizer: MethodError(f=Main.var"#6#7"{Int32}(handle=5), args=(Array{UInt8, 1}(dims=(191554446,), mem=Memory{UInt8}(191554446, 0x7f377f318010)[0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, … (screenfuls of numbers ad nauseum, probably dumping the entire memory block)

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [November 12, 2024, 10:53am UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/6 "2024-11-12T10:53:36Z")

</div>

I think the passed closure requires one argument (see the MWE in the docstring of `finalizer`; was my bad, I updated the above answer). Try

```julia
return finalizer(dataRef) do ref
    @ccall mylib.closeRecord(handle::Cint)::Cvoid
end

```

---

<div class="post-metadata">

**Author:** ![gmcardle](https://avatars.discourse-cdn.com/v4/letter/g/34f0e0/32.png) [@gmcardle](https://discourse.julialang.org/u/gmcardle)\
**Post date:** [November 12, 2024, 11:20am UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/7 "2024-11-12T11:20:44Z")

</div>

Thanks, that worked, albeit surprisingly. I think this relates back to my original question: the help text indicates that finalizers can only be registered for mutable struct types. This seems quite restrictive. In the above example dataRef is just an array, so I’m surprised I “got away with it”.  
I don’t find the finalizer docstring examples really that helpful because they only show the use of a finalizer to produce a debug statement, not how it could be used in practice for really “finalizing” an object

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 12, 2024, 12:09pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/8 "2024-11-12T12:09:22Z")

</div>

> [@gmcardle](#):
>
> In the above example dataRef is just an array, so I’m surprised I “got away with it”.

Arrays qualify, although they are more magical than your typical mutable struct, in particular before Julia 1.11.

```julia
julia> ismutabletype(Array)
true

julia> isstructtype(Array)
true

```

---

<div class="post-metadata">

**Author:** ![gmcardle](https://avatars.discourse-cdn.com/v4/letter/g/34f0e0/32.png) [@gmcardle](https://discourse.julialang.org/u/gmcardle)\
**Post date:** [November 12, 2024, 1:14pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/9 "2024-11-12T13:14:03Z")

</div>

Ah, that explains it! I didn’t expect that.  
thanks!

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [November 12, 2024, 2:49pm UTC](https://discourse.julialang.org/t/example-of-registering-a-finalizer-for-unsafe-wrapped-data-from-ccall/122499/10 "2024-11-12T14:49:55Z")

</div>

In Julia 1.11 I think this should be:

```julia
return finalizer(dataRef.ref.mem) do x
   closefunc()
end

```

Because the wrapping Array can get finalized while the underlying memory is still being used.  
This is what Mmap.jl does.

> <https://github.com/JuliaLang/julia/blob/001c666086de77101b6937c3d31f0888a35325db/stdlib/Mmap/src/Mmap.jl#L255-L256>

Another tricky thing is that as far as I can tell, finalizers can be concurrently run on different threads, so you need to ensure the C library is thread-safe for this to work. PythonCall.jl has some example finalizers for dealing with non-thread-safe C libraries.
