I’m having a problem with a Julia function which returns a pointer to an object. The pointer is coded in 8 bytes. This function has a C interface to be used form a C program.
When I use this function in C, only the half of the value (the 4 less signicant bytes) is retrived. So, I can’t reuse the pointed object…
For information, I am working on a 64-bit Linux
To be more explicit, here’s my Julia code
type MyType
param1::Int
param2::Int
function MyType()
new(1,2)
end
end
Base.@ccallable function create_object()::Ptr{Void}
newobject = MyType()
objectpointer = pointer_from_objref(newobject)
println("Simple object pointer :")
print_pointer(objectpointer)
return objectpointer
end
Base.@ccallable function print_pointer(inputpointer::Ptr{Void})::Cint
println("pointer : ")
println(inputpointer)
return 0
end
Hello yuyi !
Thank you for your answer. While I was responding to you, I found that I didn’t declare explicitely the extern functions. Indeed, when the functions are explicitely declared , it works OK.
Your answer helped me to solve my problem. Thank you very much.
Anyway, why do you say that the Julia function is wrong? Why do you say that the pointer can be garbage?
Is there any way to control garbage collector in order to avoid the object from being unreferenced?
Now, my C code is
// Standard headers
#include <string.h>
#include <stdint.h>
#include <stdio.h>
// Julia headers (for initialization and gc commands)
// #include "uv.h"
#include "julia.h"
#ifdef JULIA_DEFINE_FAST_TLS // only available in Julia 0.7+
JULIA_DEFINE_FAST_TLS()
#endif
extern jl_value_t* create_object();
extern void print_pointer(jl_value_t*);
extern void print_object(jl_value_t*);
// main function (windows UTF16 -> UTF8 argument conversion code copied from julia's ui/repl.c)
int main(int argc, char *argv[])
{
// initialization
libsupport_init();
// jl_options.compile_enabled = JL_OPTIONS_COMPILE_OFF;
jl_options.image_file = "libjulia_example";
julia_init(JL_IMAGE_JULIA_HOME);
jl_value_t* simple_ptr;
simple_ptr = create_object();
printf("simple object created\n");
print_pointer(simple_ptr);
print_object(simple_ptr);
// JL_GC_POP();
// Cleanup and gracefully exit
jl_atexit_hook(0);
return 0;
}
With a new Julia function :
Base.@ccallable function print_object(inputpointer::Ptr{Void})::Cint
println("object my_type : ")
retrieved_object = unsafe_pointer_to_objref(inputpointer)
println(retrieved_object.param1)
println(retrieved_object.param2)
return 0
end
Julia will be able to free the memory immediately, since it can see that the object (which “holds” the memory) is no longer referenced after the call to pointer_from_objref.
You’d need some way of keeping a reference to that object in Julia.
I find it easier for Julia code to call into C code, so that the objects are still referenced in the Julia memory, rather than trying to return pointers to Julia objects to C code.
Not impossible but that’s not the the right approach. You should just return the object directly and use Any or appropriate Ref as the return/argument type instead. cfunction certainly support this so I assume @ccallable does too.
Hi Yichao,
I understand your point of view. However, the reason that I am trying to do that this way is that I am reusing an existing Julia project and it have a large amonut of complex types, so it would represent a huge amount of work to translate everything to C. Besides, the C-side doesn’t need to read or handle the returned objects, but only to keep them to pass them back again as parameters.
Thus, I prefer to try with my approach.
Now, my question is : How can I safe my Julia objects to avoid them to be collected ? You say this is not impossible. May you guide me to do that. I don’t find the right way to do that.
Thank you in advance.
Make sure they are still referenced on the Julia side (the Julia object, not a Ptr to the memory where one is/was (it can disappear when GC happens otherwise).