Re: opaque pointers and metatype

  • From: Richard Hundt <richardhundt@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Tue, 04 Mar 2014 10:04:15 +0100

On 3/4/14 3:01 AM, Cosmin Apreutesei wrote:
>> I don't think it can be done as long as you're missing the size.
> I'm not missing the size, pthread_mutex_t is a pointer and it's size
> is sizeof(pthread_mutex_t), i.e. sizeof(void*).
Ah, there's our confusion. pthread_mutex_t not a pointer on Darwin, and
neither is it on my Linux box. Here are the Darwin definitions:

struct _opaque_pthread_mutex_t { long __sig; char __opaque[56]; };
typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
typedef __darwin_pthread_mutex_t pthread_mutex_t;

For Linux;
http://repo-genesis3.cbi.utsa.edu/crossref/heccer/usr/include/bits/pthreadtypes.h.html

>
>> Obviously the key difference is that the library itself has allocates
>> storage.
> Here too, the library allocates storage. It's just a difference in
> style. Some APIs return an opaque* while others _take_ and opaque**
> (two-stars), or an &opaque*, which is the same thing, and fill that
> out.
I don't know what library you have, so not sure. I can see how the
pthreads case can't work though. It's not a pointer-to-a-pointer
argument in this case.
>
>> allocation. In this case`pthread_mutex_init` just initializes and
>> assumes it has a big enough blob of memory.
> pthread_mutex_init() assumes it has an address location to write to
> and nothing more.
>
Yeah, if a pthread_mutex_t were a pointer, I'd agree. Maybe it is on
some systems. Dunno.

The case I can think of is:

int getaddrinfo(const char *node, const char *service,
                       const struct addrinfo *hints,
                       struct addrinfo **res);

Here the result would match your pattern. But you have the size problem
again with the `hints` parameter. In this case though, it's not opaque,
and you'd have to cdef the struct definition anyway to extract the
information, so it still doesn't match your case. But you can still give
it a metatable and a destroy method:

local ffi = require('ffi')
ffi.cdef[[
typedef struct addrinfo addrinfo_t;

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);

void freeaddrinfo(struct addrinfo *ai);
]]

local C = ffi.C

ai_mt = { }
ai_mt.__index = ai_mt
ai_mt.destroy = function(self)
   C.freeaddrinfo(self)
end

ffi.metatype('addrinfo_t', ai_mt)

local addrs = ffi.new('addrinfo_t*[1]')
C.getaddrinfo("0.0.0.0", "tcp", nil, addrs)

local addr = addrs[0]
addr:destroy()


Other related posts: