So here are my use cases:
-
Create the object and pass it into the C function. After the call is finished, the object is usually discarded.
-
The C function may return the struct. In which case, an
unpack
function is created to extract the data into Julia objects. It would do the same thing as listed above - a one dimensional array of native Julia values is returned ([2.0, 3.0]
)
So the risk lies with #1 - GC may kick in and overwrite what ar
was pointing to with some garbage and the C call could fail.
#2 isn’t really a problem because the memory is allocated by the C library not by Julia, hence it’s not going to be picked up by GC.
I’m not sure how to maintain the pointer though. I went through the PyCall code but don’t really understand what it does. I understand a Dict
isn’t performant but if that’s just a data structure thing then I will adjust according to my usage pattern and use a different data structure as necessary. Also, if maintain this pointer then I would have to register a finalizer
function when the parent object is freed. Is that right?
Another idea is to create another wrapper struct that contains the julia data the underlying C struct. More concretely:
struct Foo
ar::Vector{Bar}
obj::Bar
end
and then the binding function would look like:
function callme(x)
ccall((:func, LIB), Ptr{Bar}, (Ptr{Bar},), x)
end
and I would have to deference to the object before calling the binding function:
callme(Ref(foo.obj))