[erlang-questions] how can I make nif shared libraries

Paul Davis paul.joseph.davis@REDACTED
Wed Dec 22 21:12:31 CET 2010


On Wed, Dec 22, 2010 at 2:49 PM, Joe Armstrong <erlang@REDACTED> wrote:
> How do link shared libraries with nifs?
>
> I want to make a few nifs and put them in a shared library.
> The problem is that the my nif library in its turn calls things in
> other shared libraries. And when I load my nif library the other
> referenced shared libraries
> are not loaded.
>
> I made a little example to illustrate this:
>
> I have a file niftest.c with the following nif
>
>   extern int other_lib_mult(int, int);
>
>   static ERL_NIF_TERM mult(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
>   {
>      int a,b,c;
>      enif_get_int(env, argv[0], &a);
>      enif_get_int(env, argv[0], &b);
>      c = other_lib_mult(a, b);
>      return enif_make_int(env, c);
>   }
>
> I make a shared library called niftest.so
> with this command
>
> gcc -m32 -O3 -fPIC -bundle -flat_namespace -undefined suppress
> -fno-common -Wall -o niftest.so niftest.c -I
> /usr/local/lib/erlang/usr/include/
>

You need to link against lib.so when you link the nif (in this case,
you're compiling and linking in one step, so it should be added here).
This would theoretically be done by adding -llib to your command line,
but see below for a note on the use of lib as a library name.

You also need to make sure that your library is on the linker path
during runtime as that's how the dynamic library loader will find it
(which happens when you load the nif in Erlang, it spiders out to the
libraries that library needs until it can resolve all the required
symbols).

Also an alternative approach would be to make your lib.so a static
library lib.a and then link your nif against that which removes some
of these issues in finding libraries.

As an aside, I wouldn't name the other library lib, because the linker
will play games with files name lib$(something).so. I don't remember
the specifics for the name resolution off the top of my head, but its
the sort of thing that could cause confusion.

> Which makes the shared library.
>
> other_lib_mult is is lib.c and I make a shared library lib.so with a
> similar command to the above
>
> When I try to load niftest.so erlang says
>
> {error,{load_failed,"Failed to load NIF library: 'dlopen(./niftest.so,
> 2): Symbol not found: _other_lib_mult\n  Referenced from:
> /Users/joe/code/nifs/nif2/niftest.so\n  Expected in: flat namespace\n
> in /Users/joe/code/nifs/nif2/niftest.so'"}}
>
> This is running on mac os-x.
>
> Also do all the shared libraries have to be compiled for 32 bit, or
> can I pick and mix
> with 64 bit code. Without the -m32 flag nothing works and some of the
> shared libraries
> I want to call were compiled as 64 bit.
>

You have to have everything compiled for a single architecture. This
is a common gotchya in exactly this circumstance where you need a
library in a NIF that's a different architecture than what Erlang was
compiled with. If you have mismatched architectures you can also
trigger this symbol not found error. If things appear as though they
should be working a quick check is to do "nm -arch x86_64" to check
for 64bit symbols (or -arch i386 symbols if Erlang was compiled
32bit).

Another layer of this gotchya is that as of OS X 10.6, gcc will
compile 64bit by default where as Erlang on OS X will compile 32bit by
default.

I generally find it easiest to make sure everything is compiled as 64bit.

HTH,
Paul Davis

> Cheers
>
> /Joe
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
>


More information about the erlang-questions mailing list