【问题标题】:Building a shared library using gcc [closed]使用 gcc 构建共享库 [关闭]
【发布时间】:2011-04-05 01:07:15
【问题描述】:

已解决。请参阅下面的更正(标记为 FIXED)。

我在使用 gcc 创建共享库时遇到问题。

我创建了一个小示例项目,它与我正在处理的实际项目的结构非常相似。我在此处将其作为 tar.gz 存档提供:

http://209.59.216.197/libtest.tar.gz

已修复:我在此处提供了固定版本:
http://209.59.216.197/libtest_fixed.tar.gz

在这个示例项目中,我有一个应用程序 (app),它加载我在运行时编写的共享库 (libshared.so) 并调用共享库定义的函数:function_inside_shared_lib()。

反过来,这个共享库使用在静态库 (libstatic.a) 中定义的函数:function_inside_static_lib()。

问题是当我构建共享库时,符号“function_inside_shared_lib”没有被导出。我使用“nm”检查了共享库,但符号不存在。我想知道我用来创建共享库的命令是否正确:

g++ -g -ggdb -fPIC -rdynamic -I ../static -c shared.cpp -o shared.o
g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so

已修复:正确的命令是:

g++ -g -ggdb -fPIC -rdynamic -I../static -c shared.cpp -o shared.o
g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic

我尝试了使用和不使用 -rdynamic 以及使用和不使用 -fPIC 的这些命令。结果总是一样的。

我正在使用 Ubuntu 10.04(64 位)和 g++ 版本 4.4.3。

完整的示例项目如下。 (或者您可以使用我帖子顶部的链接下载存档)。

serg@rodent:~/libtest$ ls
应用共享静态

以下是三个组件:

组件 1:一个静态库,定义了一个名为 function_inside_static_lib() 的函数

这包括以下内容:

serg@rodent:~/libtest$ cd static/  
serg@rodent:~/libtest/static$ ls  
static.cpp  static.h

static.h

// Header file for the static library

int function_inside_static_lib(int arg1, int arg2);

static.cpp

// Source file for the static library

#include <iostream>
using namespace std;

#include "static.h"

int function_inside_static_lib(int arg1, int arg2)
{
    cout << "In function_inside_static_lib()" << endl;

    // Return the sum
    int result = arg1 + arg2;
    return result;
}

组件 2:使用静态库并定义新函数的共享库。

serg@rodent:~/libtest$ cd shared
serg@rodent:~/libtest/shared$ ls
shared.cpp

shared.cpp

// The shared library only has one source file.

// The shared library uses the static one.
#include "static.h"

#include <iostream>
using namespace std;

int function_inside_shared_lib(int arg1, int arg2)
{
    cout << "In function_inside_shared_lib()" << endl;

    cout << "Calling function_inside_static_lib()" << endl;
    int result = function_inside_static_lib(arg1, arg2);

    return result;
}

组件 3:使用共享库的应用程序。

serg@rodent:~/libtest$ cd app
serg@rodent:~/libtest/app$ ls
应用程序.cpp

app.cpp

已修复:由于 C++ 符号被破坏,要搜索的正确函数名称是 _Z26function_inside_static_libii 而不是 function_inside_static_lib

// The application loads the shared library at runtime.

#include <dlfcn.h>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
    void *handle;
    int (*function_inside_shared_lib)(int, int);
    char *error;

    int arg1 = 3;
    int arg2 = 7;

    cout << "app: loading the shared library." << endl;
    handle = dlopen ("libshared.so", RTLD_LAZY);
    if (!handle) {
        cout << "Error: Failed to open shared library." << endl;
        cout << dlerror() << endl;
        return -1;
    }

    cout << "app: Looking for function_inside_shared_lib" << endl;

    // The next line is now FIXED:
    function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");

    if ((error = dlerror()) != NULL)  {
        cout << "Error: Could not find the function." << endl;
        cout << error << endl;
        return -1;
    }

    cout << "app: Calling function_inside_shared_lib(" << arg1 << ", " << arg2 << ")" << endl;
    int result = (*function_inside_shared_lib)(arg1, arg2);

    cout << "app: The result is " << result << endl;

    dlclose(handle);
    return 0;
}

这是我用来构建所有这些组件的命令。请注意,我希望调试符号在最终生成的应用程序中可用。理想情况下,我希望能够在应用程序内进行回溯,并查看共享库和静态库中的符号。

1:构建静态库。我觉得这一步没问题:

serg@rodent:~/libtest/static$ g++ -g -ggdb -c static.cpp -o static.o # 查看下面的FIXED版本
serg@rodent:~/libtest/static$ ar rcs libstatic.a static.o
serg@rodent:~/libtest/static$ ls
libstatic.a static.cpp static.h static.o

已修复:上面的第一个命令也必须包含 -fPIC。正确的命令是

g++ -g -ggdb -fPIC -c static.cpp -o static.o

2:构建共享库。我很确定这是我出错的地方。

serg@rodent:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -I ../static -c shared.cpp -o shared.o
serg@rodent:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so # FIXED 版本见下文 serg@rodent:~/libtest/shared$ ls
libshared.so shared.cpp shared.o

已修复:上面的第二个命令应该是:

g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic

此时,如果我运行 nm 来检查 libshared.so 中的符号,我在任何地方都看不到 function_inside_shared_lib(),即使使用 nm 的 -a 和 -D 选项也是如此。 (但是,我确实在 shared.o 中看到了它)。

编辑:通过上述修复,符号显示为_Z26function_inside_shared_libii

3:构建应用程序:

首先,将共享库复制到app文件夹中:

serg@rodent:~/libtest$ cp shared/libshared.so app/
serg@rodent:~/libtest$ cd app
serg@rodent:~/libtest/app$ ls
app.cpp libshared.so

现在编译:

serg@rodent:~/libtest/app$ g++ -g -ggdb -ldl -L。 -lshared app.cpp -o 应用
serg@rodent:~/libtest/app$ ls
app app.cpp libshared.so

如果我尝试运行:

serg@rodent:~/libtest/app$ ./app
应用程序:加载共享库。
应用程序:寻找 function_inside_shared_lib
错误:找不到函数。
/home/serg/libtest/app/libshared.so:未定义符号:function_inside_shared_lib

这是有道理的,因为我也无法使用 nm 看到 function_inside_shared_lib(),这意味着我可能在第 2 步中错误地构建了共享库。

如何在第二步中修复我的命令,以便正确导出 function_inside_shared_lib?

如果您发现我在做任何奇怪的事情,请随时给我任何其他建议。我还是个初学者。

【问题讨论】:

标签: c++ gcc shared-libraries


【解决方案1】:

这里有一些错误:

libshared.so 为空

您的 Makefile 实际上并没有链接到 shared.o 中,它只是创建了一个空的共享库。 改变

g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -lstatic -o shared/libshared.so 

g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -o shared/libshared.so shared/shared.o -lstatic

-lstatic 必须在 shared/shared.o 之后,因为您必须按照其依赖项的相反顺序指定静态库。

共享库中的所有对象文件都需要-fPIC

您创建一个在静态库中链接的共享库。该静态库还必须使用 -fPIC 进行编译,否则您将创建一个共享库,其中某些部分无法重新定位。改变

g++ -g -ggdb -c static/static.cpp -o static/static.o

g++ -fPIC -g -ggdb -c static/static.cpp -o static/static.o

C++ 符号被破坏

当您从 C++ 代码创建共享库时,函数名称和类似名称会得到 mangeled 这意味着没有与您尝试动态加载的字符串“function_inside_static_lib”匹配的函数名称。在静态库上运行 nm,你会看到它实际上被命名为 "_Z26function_inside_static_libii" 。您可以运行 nm -C 来漂亮地打印 C++ 名称。

这意味着您在 app.cpp 中的代码必须是:

 function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");

如果您想动态 (dlopen) 从共享库中获取某些内容,通常更喜欢使用 C 而不是 C++ 从共享对象中导出函数,这也是原因之一。过去,C++ 名称修饰因编译器而异,尽管现在他们似乎都同意一个不会改变的标准。使用 C 语言更简单,共享库中的符号将与您在源代码中提供的相同。

【讨论】:

  • 谢谢!做到了!
【解决方案2】:

因此,在第 2 步中,您没有指定 shared.o。所以,而不是:

g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so

你应该这样做:

g++ -g -ggdb -fPIC -rdynamic -shared -L ../static shared.o -lstatic -o libshared.so

shared.o 在 -lstatic 之前也很重要。否则链接器将找不到函数并让它'未定义'。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2013-07-10
    相关资源
    最近更新 更多