已解决。请参见以下更正 (标有 FIXED)。
我在使用gcc创建共享库时遇到了问题。
我创建了一个小样本项目,它与我正在工作的实际项目的结构非常相似。我已将其制作成tar.gz存档,并上传至以下地址:
http://209.59.216.197/libtest.tar.gz
FIXED: 我已将修正版放在以下地址:
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的这些命令。结果总是一样。
我正在使用g ++版本4.4.3的Ubuntu 10.04 (64位)。
以下是完整的示例项目。(或者您可以使用我的文章顶部的链接下载档案)。
serg@rodent:~/libtest$ ls
app shared static
以下是三个组件:
组件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
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;
}
这是我用于构建所有组件的命令。请注意,我希望在最终生成的应用程序中提供调试符号。理想情况下,我希望能够在应用程序内部进行回溯,并查看共享库和静态库中的符号。1:构建静态库。我认为这一步没问题:
```bash serg@rodent:~/libtest/static$ g++ -g -ggdb -c static.cpp -o static.o serg@rodent:~/libtest/static$ ar rcs libstatic.a static.o serg@rodent:~/libtest/static$ ls libstatic.a static.cpp static.h static.o ```
**修正:上面的第一个命令也必须包括 -fPIC。正确的命令是:**
```bash g++ -g -ggdb -fPIC -c static.cpp -o static.o ```
2:构建共享库。我很确定这是我出错的地方。
```bash 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 serg@rodent:~/libtest/shared$ ls libshared.so shared.cpp shared.o ```
**修正:上面的第二个命令应该是:**
```bash g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic ```
此时,如果我运行 nm 命令来检查 libshared.so 中的符号,我无论是否使用 nm 的 -a 和 -D 选项,都看不到 `function_inside_shared_lib()` 函数的任何信息(但是,我可以在 shared.o 文件中看到它)。
编辑:使用上面的修正,符号将显示为 `_Z26function_inside_shared_libii`。
3:构建应用程序:
首先将共享库复制到应用程序文件夹中:
```bash 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 app serg@rodent:~/libtest/app$ ls app app.cpp libshared.so
如果我尝试运行: serg@rodent:~/libtest/app$ ./app app:正在加载共享库。 app:查找function_inside_shared_lib。 错误:找不到该函数。 /home/serg/libtest/app/libshared.so:未定义的符号:function_inside_shared_lib。
这是因为在步骤2中,我可能没有正确地构建共享库,使用nm也看不到function_inside_shared_lib(),因此需要修复第二步命令以使其正确导出function_inside_shared_lib。如果您注意到我执行任何奇怪操作,请随时给予建议。我还是初学者。