使用gcc构建共享库
已解决。请参阅下面的更正(标记为FIXED)。使用gcc构建共享库
我在使用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
FIXED:正确的命令是:
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。
下面是完整的示例项目。 (或者您可以使用我的文章顶部的链接下载该档案)。
[email protected]:~/libtest$ ls
app shared static
这里有三个组成部分:
组分1:定义一个函数调用function_inside_static_lib()静态库。
这包括以下的:
[email protected]:~/libtest$ cd static/ [email protected]:~/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:使用静态库并定义新功能的共享库。
[email protected]:~/libtest$ cd shared
[email protected]:~/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:使用共享库中的应用。
[email protected]:~/libtest$ cd app
[email protected]:~/libtest/app$ ls
app.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;
}
这里是我用来构建所有的命令se组件。请注意,我希望调试符号在最终生成的应用程序中可用。理想情况下,我希望能够在应用程序内部进行回溯,并查看共享库和静态库中的符号。
1:构建静态库。我觉得我很好用此步骤:
[email protected]:~/libtest/static$ g++ -g -ggdb -c static.cpp -o static.o # See the FIXED version just below
[email protected]:~/libtest/static$ ar rcs libstatic.a static.o
[email protected]:~/libtest/static$ ls
libstatic.a static.cpp static.h static.o
固定:上面的第一个命令必须包含-fPIC为好。正确的命令是
g++ -g -ggdb -fPIC -c static.cpp -o static.o
2:构建共享库。我很确定这是我出错的地方。
[email protected]:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -I ../static -c shared.cpp -o shared.o
[email protected]:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so # See just below for FIXED version [email protected]:~/libtest/shared$ ls
libshared.so shared.cpp shared.o
FIXED:上述第二个命令应该是:
g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic
此时,如果用完纳米至检查内部libshared.so符号,我没有看到function_inside_shared_lib()在任何地方,即使使用nm的-a和-D选项。 (但是,我确实在shared.o中看到它)。
编辑:与上面的修复程序,该符号显示为_Z26function_inside_shared_libii
。
3:构建应用程序:
首先,共享库复制到应用程序文件夹:
[email protected]:~/libtest$ cp shared/libshared.so app/
[email protected]:~/libtest$ cd app
[email protected]:~/libtest/app$ ls
app.cpp libshared.so
现在编译:
[email protected]:~/libtest/app$ g++ -g -ggdb -ldl -L. -lshared app.cpp -o app
[email protected]:~/libtest/app$ ls
app app.cpp libshared.so
如果我尝试运行:
[email protected]:~/libtest/app$ ./app
app: loading the shared library.
app: Looking for function_inside_shared_lib
Error: Could not find the function.
/home/serg/libtest/app/libshared.so: undefined symbol: function_inside_shared_lib
这很有道理,因为我看不到使用nm的function_inside_shared_lib(),这意味着我可能在第2步中错误地构建了共享库。
如何在第二步修复我的命令以便function_inside_shared_lib正确导出?
如果你发现我做了什么奇怪的事情,还可以给我任何其他建议。我还是个初学者。
这里有几个误区:
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.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");
这是它往往preferrable从用C代替C++,如果你想动态共享对象导出功能的原因之一(dlopen的)从共享库中获取某些内容。过去的C++名称在编译器和编译器中各不相同,尽管目前它们似乎已经同意一个不会改变的标准。使用C更简单,共享库中的符号与源代码中的符号相同。
谢谢!这做到了! – 2010-08-28 00:47:19
因此,在第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。否则,链接器将不会找到该函数并让它'未定义'。
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries。html – Anycorn 2010-08-27 22:27:44
构建共享对象库的命令看起来不正确 - 它没有提到shared.o。你输入的内容是否正确? – Beta 2010-08-27 23:08:43
这是一个问题还是十七个问题或十七个答案?我不能告诉任何更多... – 2012-12-27 22:05:32