SOLVED. See below for the corrections (labeled FIXED).
解决了。请参阅下面的更正(贴标)。
I'm having trouble creating a shared library using gcc.
我很难使用gcc创建一个共享库。
I created a little sample project that closely mirrors the structure of the actual project I'm working on. I've made it available as a tar.gz archive here:
我创建了一个小样本项目,它与我正在进行的实际项目的结构密切相关。我已经把它当成焦油了。广州档案:
http://209.59.216.197/libtest.tar.gz
http://209.59.216.197/libtest.tar.gz
FIXED: I've made the fixed version available here:
http://209.59.216.197/libtest_fixed.tar.gz
修复:我已经在这里提供了固定版本:http://209.59.216.197/libtest_fix.tar.gz。
In this sample project, I have an application (app) that loads a shared library that I wrote (libshared.so) at runtime and calls a function that the shared library defines: function_inside_shared_lib().
在这个示例项目中,我有一个应用程序(app),它加载我在运行时编写的共享库(libsharedso),并调用共享库定义的函数:function_inside_shared_lib()。
In turn, this shared library uses a function defined inside a static library (libstatic.a): function_inside_static_lib().
反过来,这个共享库使用静态库中定义的函数(libstatic.a): function_inside_static_lib()。
The problem is when I build the shared library, the symbol "function_inside_shared_lib" does not get exported. I examined the shared library using "nm" and the symbol wasn't there. I am wondering if the command I am using to create the shared library is correct:
问题是当我构建共享库时,符号“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.sog++ -g -ggdb -fPIC -rdynamic -I ../静态- c共享。cpp - o共享。o g++ g -ggdb -fPIC -rdynamic -共享-L ../静态-lstatic - o libshared.so
FIXED: The correct commands are:
修正:正确的命令是:
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 -lstaticg++ -g -ggdb -fPIC -rdynamic -I../静态- c共享。cpp - o共享。o g++ g -ggdb -fPIC -rdynamic -共享-L../静态- o libshared。所以共享。o -lstatic
I tried these commands with and without -rdynamic, as well as with and without -fPIC. The results are always the same.
我尝试了这些命令,没有-rdynamic,也没有-fPIC。结果总是一样的。
I am using Ubuntu 10.04 (64-bit) with g++ version 4.4.3.
我使用的是ubuntu10.04(64位)和g++版本4.4.3。
The full sample project follows. (Or you can download the archive using the link at the top of my post).
完整的示例项目如下。(或者你可以在我的帖子顶部用链接下载档案)。
serg@rodent:~/libtest$ ls
app shared static~/libtest$ ls应用程序共享静态。
Here are the three components:
以下是三个组成部分:
Component 1: A static library that defines a function called function_inside_static_lib().
组件1:定义一个名为function_inside_static_lib()函数的静态库。
This consists of the following:
这包括以下内容:
serg@rodent:~/libtest$ cd static/ serg@rodent:~/libtest/static$ ls static.cpp static.h
static.h
static.h
// Header file for the static library
int function_inside_static_lib(int arg1, int arg2);
static.cpp
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;
}
Component 2: A shared library that uses the static library and defines a new function.
组件2:使用静态库并定义新函数的共享库。
serg@rodent:~/libtest$ cd shared
serg@rodent:~/libtest/shared$ ls
shared.cppserg@rodent:~/libtest$ cd共享serg@rodent:~/libtest/共享$ 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;
}
Component 3: An application that uses the shared library.
组件3:使用共享库的应用程序。
serg@rodent:~/libtest$ cd app
serg@rodent:~/libtest/app$ ls
app.cppserg@rodent:~/libtest$ cd应用程序serg@rodent:~/libtest/app$ ls app.cpp。
app.cpp
app.cpp
FIXED: Because C++ symbols get mangled, the correct function name to search for is _Z26function_inside_static_libii
instead of function_inside_static_lib
修正:由于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;
}
Here are the commands I'm using to build all of these components. Note that I want debugging symbols to be available in the final resulting app. Ideally, I want to be able to do a backtrace inside the app and see symbols from both the shared library and the static library.
下面是我用来构建所有这些组件的命令。请注意,我希望在最终的应用程序中可以使用调试符号。理想情况下,我希望能够在应用程序中进行回溯,并从共享库和静态库中查看符号。
1: Building the static library. I think I'm fine with this step:
1:构建静态库。我觉得这一步很好:
serg@rodent:~/libtest/static$ g++ -g -ggdb -c static.cpp -o static.o # See the FIXED version just below
serg@rodent:~/libtest/static$ ar rcs libstatic.a static.o
serg@rodent:~/libtest/static$ ls
libstatic.a static.cpp static.h static.o@ serg@rodent:~/libtest/静态$ g++ g -ggdb -c静态。cpp - o静态的。在serg@rodent下面看到固定版本:~/libtest/静态$ ar rcs libstatic。一个静态的。o serg@rodent:~ / libtest /静态ls libstatic美元。一个静态的。cpp静态的。h static.o
FIXED: The first command above must include -fPIC as well. The correct command is
固定:上面的第一个命令必须包括-fPIC。正确的命令是
g++ -g -ggdb -fPIC -c static.cpp -o static.o
g++ -g -ggdb -fPIC -c静态。cpp - o static.o
2: Building the shared library. I'm pretty sure this is where I'm going wrong.
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 # See just below for FIXED version serg@rodent:~/libtest/shared$ ls
libshared.so shared.cpp shared.o@ serg@rodent:~/libtest/共享$ g++ -g -ggdb -fPIC -rdynamic -I ../静态- c共享。cpp - o共享。@ serg@rodent:~/libtest/共享$ g+ -g -ggdb -fPIC -rdynamic -共享-L ../静态-lstatic - o libshared。因此,请参见下面的固定版本serg@rodent:~/libtest/共享$ ls libshared。所以共享。cpp shared.o
FIXED: The second command above should be:
固定:上面的第二条命令应该是:
g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic
g++ -g -ggdb -fPIC -rdynamic -共享-L../静态- o libshared。所以共享。o -lstatic
At this point, if I run nm to examine the symbols inside libshared.so, I don't see function_inside_shared_lib() anywhere, even with the -a and -D options for nm. (However, I do see it inside shared.o).
此时,如果我运行nm来检查libshared中的符号。因此,我在任何地方都看不到function_inside_shared_lib(),即使是对nm的-a和-D选项。(不过,我确实看到了它的内部。)
EDIT: With the fix above, the symbol appears as _Z26function_inside_shared_libii
.
编辑:在上面的修复中,这个符号显示为_Z26function_inside_shared_libii。
3: Building the app:
3:构建应用程序:
First, copy the shared library into the app folder:
首先,将共享库复制到app文件夹:
serg@rodent:~/libtest$ cp shared/libshared.so app/
serg@rodent:~/libtest$ cd app
serg@rodent:~/libtest/app$ ls
app.cpp libshared.soserg@rodent:~ / libtest $ cp / libshared共享。所以应用程序/ serg@rodent:~/libtest$ cd应用程序serg@rodent:~/libtest/app$ ls app.cpp libsharedso。
Now compile:
现在编译:
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$ g++ g -ggdb -ldl -L。-lshared app.cpp -o应用程序serg@rodent:~/libtest/app$ ls app.cpp libsharedso。
If I try to run:
如果我试着跑:
serg@rodent:~/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@ serg@rodent:~/libtest/app$ ./app应用程序:加载共享库。应用程序:查找function_inside_shared_lib错误:无法找到函数。/home/serg/libtest/app/libshared.所以:未定义符号:function_inside_shared_lib
This makes sense because I could not see function_inside_shared_lib() using nm either, which means I'm probably building the shared library incorrectly in step 2.
这很有意义,因为我不能使用nm来查看function_inside_shared_lib(),这意味着我可能在步骤2中错误地构建了共享库。
How can I fix my command in the second step so that function_inside_shared_lib gets exported correctly?
如何在第二个步骤中修复我的命令,使function_inside_shared_lib能够正确地导出?
Also feel free to give me any other advice if you notice that I'm doing anything odd. I'm still a beginner.
如果你注意到我做了什么奇怪的事情,你也可以给我任何其他建议。我还是一个初学者。
2 个解决方案
#1
9
There's a few errors here:
这里有一些错误:
libshared.so is empty
libshared。所以是空的
Your Makefile doesn't actually link in the shared.o , it just creates an empty shared library. Change
您的Makefile实际上并没有链接到共享。它只是创建了一个空的共享库。改变
g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -lstatic -o shared/libshared.so
to
来
g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -o shared/libshared.so shared/shared.o -lstatic
The -lstatic have to come after shared/shared.o as you have to specify static libraries in reverse order of their dependencies.
lstatic必须在共享/共享之后进行。o由于必须以相反的顺序指定静态库。
-fPIC is needed on all object files in a shared library
-fPIC在共享库中的所有对象文件上都是必需的。
You create a shared library that links in a static library. That static library also have to be compiled with -fPIC, otherwise you're creating a shared library where some parts of it cannot be relocated. Change
您可以在静态库中创建一个共享库。静态库也必须用-fPIC编译,否则您将创建一个共享库,其中一些部分不能被重新定位。改变
g++ -g -ggdb -c static/static.cpp -o static/static.o
to
来
g++ -fPIC -g -ggdb -c static/static.cpp -o static/static.o
C++ symbols get mangled
c++符号被破坏
As you're creating a shared library from C++ code, function names and similar gets mangeled This means there is no function name matching the string "function_inside_static_lib" which you try to dynamically load. run nm on the static library, you'll see it's actually named "_Z26function_inside_static_libii" . You can run nm -C to pretty print C++ names.
当您从c++代码创建一个共享库时,函数名和类似的函数会被修改,这意味着没有函数名匹配字符串“function_inside_static_lib”,您尝试动态加载它。在静态库上运行nm,您会看到它实际上被命名为“_Z26function_inside_static_libii”。你可以运行nm -C到漂亮的打印c++名称。
This means your code in app.cpp have to be:
这意味着您的代码在app.cpp中必须是:
function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");
This is one of the reasons it's often preferrable to export functions from shared objects using C instead of C++ if you want to dynamically (dlopen) fetch something from a shared library. The C++ name mangling have in the past varied from compiler to compiler, though these days they seem to have all agreed to a standard that won't be changing. With C it's simpler, and the symbols in the shared library will be the same as you gave them in your source code.
这是一个原因,它通常可以从共享对象中使用C而不是c++来导出函数,如果您想动态地(dlopen)从共享库中获取一些东西。过去,c++的名称已经从编译器变成了编译器,尽管现在他们似乎已经同意了一个不会改变的标准。与C相比,它更简单,而且共享库中的符号将与您在源代码中给出的符号相同。
#2
2
So, in step 2 you don't specify shared.o. So, instead of:
所以,在步骤2中,你没有指定sharo .o。因此,而不是:
g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so
You should do:
你应该做的是:
g++ -g -ggdb -fPIC -rdynamic -shared -L ../static shared.o -lstatic -o libshared.so
Also it is important that shared.o is before -lstatic. Otherwise the linker will not find the function and let it 'undefined'.
同样重要的是分享。o是-lstatic之前。否则,链接器将无法找到该函数并让它“未定义”。
#1
9
There's a few errors here:
这里有一些错误:
libshared.so is empty
libshared。所以是空的
Your Makefile doesn't actually link in the shared.o , it just creates an empty shared library. Change
您的Makefile实际上并没有链接到共享。它只是创建了一个空的共享库。改变
g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -lstatic -o shared/libshared.so
to
来
g++ -g -ggdb -fPIC -rdynamic -shared -Lstatic -o shared/libshared.so shared/shared.o -lstatic
The -lstatic have to come after shared/shared.o as you have to specify static libraries in reverse order of their dependencies.
lstatic必须在共享/共享之后进行。o由于必须以相反的顺序指定静态库。
-fPIC is needed on all object files in a shared library
-fPIC在共享库中的所有对象文件上都是必需的。
You create a shared library that links in a static library. That static library also have to be compiled with -fPIC, otherwise you're creating a shared library where some parts of it cannot be relocated. Change
您可以在静态库中创建一个共享库。静态库也必须用-fPIC编译,否则您将创建一个共享库,其中一些部分不能被重新定位。改变
g++ -g -ggdb -c static/static.cpp -o static/static.o
to
来
g++ -fPIC -g -ggdb -c static/static.cpp -o static/static.o
C++ symbols get mangled
c++符号被破坏
As you're creating a shared library from C++ code, function names and similar gets mangeled This means there is no function name matching the string "function_inside_static_lib" which you try to dynamically load. run nm on the static library, you'll see it's actually named "_Z26function_inside_static_libii" . You can run nm -C to pretty print C++ names.
当您从c++代码创建一个共享库时,函数名和类似的函数会被修改,这意味着没有函数名匹配字符串“function_inside_static_lib”,您尝试动态加载它。在静态库上运行nm,您会看到它实际上被命名为“_Z26function_inside_static_libii”。你可以运行nm -C到漂亮的打印c++名称。
This means your code in app.cpp have to be:
这意味着您的代码在app.cpp中必须是:
function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");
This is one of the reasons it's often preferrable to export functions from shared objects using C instead of C++ if you want to dynamically (dlopen) fetch something from a shared library. The C++ name mangling have in the past varied from compiler to compiler, though these days they seem to have all agreed to a standard that won't be changing. With C it's simpler, and the symbols in the shared library will be the same as you gave them in your source code.
这是一个原因,它通常可以从共享对象中使用C而不是c++来导出函数,如果您想动态地(dlopen)从共享库中获取一些东西。过去,c++的名称已经从编译器变成了编译器,尽管现在他们似乎已经同意了一个不会改变的标准。与C相比,它更简单,而且共享库中的符号将与您在源代码中给出的符号相同。
#2
2
So, in step 2 you don't specify shared.o. So, instead of:
所以,在步骤2中,你没有指定sharo .o。因此,而不是:
g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so
You should do:
你应该做的是:
g++ -g -ggdb -fPIC -rdynamic -shared -L ../static shared.o -lstatic -o libshared.so
Also it is important that shared.o is before -lstatic. Otherwise the linker will not find the function and let it 'undefined'.
同样重要的是分享。o是-lstatic之前。否则,链接器将无法找到该函数并让它“未定义”。