使用行为不当的共享C库在Mono p / invoke中使用“undefined symbol”

时间:2011-05-05 01:23:24

标签: c# mono pinvoke

库liba定义了某个函数f。在编写使用函数f的C程序时,除非我将-lb添加到编译命令中,否则编译将无法完成,即使我没有在我的C代码中直接引用libb中的任何内容。但是,使用p / invoke,我没有链接到库b的选项,当我从C#代码中调用函数f(当然在[DllImport(“liba”)之后)时,我得到一个符号查找错误:/usr/lib/liba.so:未定义的符号:X(X在libb中定义)。 ldd /usr/lib/liba.so不包含引用libb的行。 libb位于/ usr / lib中。我相信这个问题与Linux, Mono, shared libs and unresolved symbols基本相同,但与那种情况不同,我无法重新编译liba。有什么方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:2)

你也可以在到达p /从liba调用的代码之前从libb中导入一个函数:这将导致libb也被加载到进程中。

答案 1 :(得分:1)

这是一个糟糕的解决方案,但在这种情况下它可能是最好的:运行生成的单声道二进制文件

LD_PRELOAD=libb.so ./binary.exe 

避免这个问题。

答案 2 :(得分:0)

找到了一个很好的通用解决方案,如下面的代码所示:

  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();
            }
    }