Re: Newby questions #2: ffi.load, ffi.metatype, ffi.C

  • From: Mike Pall <mike-1207@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Sun, 1 Jul 2012 12:31:48 +0200

QuentinC wrote:
> Why can't I access the functions from linked DLLs using ffi.C ?

Because 'linking' a DLL on Windows only means the linker adds
stubs for the symbols that are actually used by the C code. And it
adds the DLL as a dependency. But it does *not* load all of the
symbols of the DLL into the global namespace.

Actually no such thing as a global namespace exists on Windows.
The C compiler instructs the linker to automatically link against
the symbols from the C library, kernel32.dll etc. and to
automatically create stubs for them. Ditto for the symbols for any
DLLs you give on the linker command line.

On Windows every DLL has its own namespace. To resolve a symbol in
a DLL, you have to explictly load the DLL. Everything else is an
illusion the compiler or the FFI creates for you.

Note that 'loading' a DLL more than one time into the same process
only increments a reference counter. The DLL is physically loaded
(actually 'mapped') into the process memory space only once.

> Yet that's precisely what is done with implicitely linked DLLs
> such as kernel32.dll or user32.dll.

These default libraries are explicitly loaded by the FFI to mirror
what you get with a C compiler on Windows.

It cannot automatically load any other DLLs you've given on the
linker command line, because AFAIK there's no (easy) way to get
their names.

> It appear that you can define a function and bind it with a
> different name with the asm keyword, as quickly shown in another
> thread.
> e.g.
> ffi.cdef[[ int myfunc (int) asm("otherfunc"); ]]
> Then reference it as myfunc in lua, allthough it is exported as
> otherfunc in the DLL.
> Is that a suitable way to arrange your function names to have more
> lua-friendly names, e.g. delete prefixes, camel case vs underscore
> names, etc. ?

That's a matter of taste. I think it may introduce more confusion
in the long term. E.g. you'll often want to look up a function
name used on the Lua side in a manual written for the C side,
which shows the C function names of course.

> Does it affect performances or is it harmless ?

No and yes.

> What would happen if there was a name clash ?

The FFI has a strict no-hand-holding policy. :-)

> local obj = ffi.C.foo_new()
> obj:method()
> 
> What is pretty cool. However, in some particular cases, it could
> also be useful to be able to write  unstead:
> foo.method(obj)

Well, that's how Lua works -- learn to use ':' for method calls.

[It's a bit complicated to explain the rationale behind this.
Summary: a foo.method lookup would require creating a short-lived
bound-method object which is kind of expensive (cf. Python). Also,
implicit method binding may cause confusion about the bound object
in some contexts (cf. Javascript).]

> Adding the ability to write that would also allow usig foo.new() to
> be used to create a new foo, unstead of going back to ffi.C or the
> DLL namespace (of course in that case the 'new' key must be added in
> the __index table)

You can simply call foo() to construct an object. If you're not
happy with the default constructor, then override __new (only in
LuaJIT git HEAD).

--Mike

Other related posts: