Shea Levy
Shea Levy

Reputation: 5435

"undefined symbol" in Mono p/invoke using misbehaving shared C library

Library liba defines a certain function f. When writing a C program that uses function f, compilation will not complete unless I add -lb to the compilation command, even though I don't refer to anything from libb directly in my C code. Using p/invoke, however, I don't have the option of linking to library b and when I call function f (after a [DllImport("liba")], of course) from within my C# code I get a symbol lookup error: /usr/lib/liba.so: undefined symbol: X (X is defined within libb). ldd /usr/lib/liba.so does not contain a row referring to libb. libb is in /usr/lib. I believe this question is essentially the same as Linux, Mono, shared libs and unresolved symbols, but unlike in that case I cannot recompile liba. Is there any way to resolve this problem?

Upvotes: 1

Views: 2120

Answers (3)

Shea Levy
Shea Levy

Reputation: 5435

Found a good general solution, exemplified in the code below:

  class MainClass
    {
            //Constants from /usr/include/bits/dlfcn.h
            private const int RTLD_LAZY = 0x00001; //Only resolve symbols as needed
            private const int RTLD_GLOBAL = 0x00100; //Make symbols available to libraries loaded later

            [DllImport("dl")]
            private static extern IntPtr dlopen (string file, int mode);

            [DllImport("a")]
            private static extern void f ();

            public static void Main (string[] args)
            {
                    //Load libb. RTLD_LAZY could be replaced with RTLD_NOW, but
                    //RTLD_GLOBAL is essential
                    dlopen("libb.so", RTLD_LAZY|RTLD_GLOBAL);

                    //Call f(), no unresolved symbol problem!
                    f();
            }
    }

Upvotes: 0

lupus
lupus

Reputation: 3973

You can also DllImport a function from libb before reaching the code that p/invokes from liba: this will cause libb to be loaded in the process as well.

Upvotes: 2

Shea Levy
Shea Levy

Reputation: 5435

This is a poor solution, but it might be the best possible under the circumstances: running the resulting mono binary with

LD_PRELOAD=libb.so ./binary.exe 

avoids the problem.

Upvotes: 1

Related Questions