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:
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?
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
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.
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.