I’ve had quite good luck using Ruby/DL to wrap a shared library, but
the lack of documentation in english is possibly preventing me from
using it in the best way.
I have a few questions:
Memory management – how do I free memory? When do I need to free
memory? I can’t seem to find any free’s in the examples, but
there are references to setting a freeing function in the PtrData
class documentation (ext/dl/doc/dl.txt)
What’s the best way to handle pointer outputs which allocate
memory? I’ve done things like the following, but I’m not sure
that it’s the best way:
say the C interface has a prototype like
int get_data(char **data, int *len);
on success, memory is allocated for a string and the pointer is
assigned to the data parameter. The length of the string is
written into the len parameter.
data = DL::malloc(DL::sizeof(“P”))
len = DL::malloc(DL::sizeof(“L”))
len.struct!(“L”, “val”)
ret = LIB.get_data(data, len)
if ret == LIB::STATUS_OK
puts "got a string of length #{len[:val]}: #{data.ptr}"
else
puts "failed to get data: #{LIB::strerror(ret)}"
end
So, my questions are:
in the above example, is there a more elegant way to deal with output
strings/data structures, etc, and how to I free the memory associated
with the output string? Is there any way for GC to know if the
memory is allocated dynamically or statically? What if the library
is responsible for freeing the memory? (clearly, I don’t know enough
about GC)
I’ve had quite good luck using Ruby/DL to wrap a shared library, but
the lack of documentation in english is possibly preventing me from
using it in the best way.
I have a few questions:
Memory management – how do I free memory? When do I need to free
memory? I can’t seem to find any free’s in the examples, but
there are references to setting a freeing function in the PtrData
class documentation (ext/dl/doc/dl.txt)
You don’t have to free memory yourself. With Ruby/DL you are dealing
with DL::PtrData objects that basically represent a memory pointer. When
there are no references to a PtrData object left, GC will collect this
object and invoke its free routine, which takes care of the allocated
memory. Take a look at PtrData#free attribute. BTW, if you know that
your library function returns a pointer to some kind of static buffer
and you don’t want a PtrData object release this buffer, just set its
free attribute to nil.
What’s the best way to handle pointer outputs which allocate
memory? I’ve done things like the following, but I’m not sure
that it’s the best way:
say the C interface has a prototype like
int get_data(char **data, int *len);
on success, memory is allocated for a string and the pointer is
assigned to the data parameter. The length of the string is
written into the len parameter.
data = DL::malloc(DL::sizeof(“P”))
len = DL::malloc(DL::sizeof(“L”))
len.struct!(“L”, “val”)
ret = LIB.get_data(data, len)
if ret == LIB::STATUS_OK
puts “got a string of length #{len[:val]}: #{data.ptr}”
else
puts “failed to get data: #{LIB::strerror(ret)}”
end
You don’t have to free memory yourself. With Ruby/DL you are dealing
with DL::PtrData objects that basically represent a memory
pointer. When there are no references to a PtrData object left, GC
will collect this object and invoke its free routine, which takes
care of the allocated memory. Take a look at PtrData#free
attribute. BTW, if you know that your library function returns a
pointer to some kind of static buffer and you don’t want a PtrData
object release this buffer, just set its free attribute to nil.
Okay, but it looks like by default PtrData#free is nil, right? Do I
always have to specify a freeing function?
It seems as though the result of DL::malloc also does not have the #free attribute set by default.