How to keep a reference for C structure to avoid GC?

So here are my use cases:

  1. Create the object and pass it into the C function. After the call is finished, the object is usually discarded.

  2. 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))