3

编辑: 我想我应该澄清一下,以防万一。我在 AIX Unix 机器上,所以我使用的是 VAC 编译器——没有 gnu 编译器。 结束编辑


我对 C/C++ 很生疏,如果这是一个简单的问题,请原谅我。

我想从我的一些 C 程序中取出常用功能,并将它们放入共享库或共享对象中。如果我在 perl 中执行此操作,我会将我的 subs 放在 perl 模块中,并在需要时使用该模块。

举个例子,假设我有这个功能:

int giveInteger()
{
    return 1034;
}

显然这不是一个真实世界的例子,但如果我想分享那个功能,我将如何进行?

我很确定我有两个选择:

  1. 将我的共享函数放在一个文件中,并在编译时将其与我的主程序一起编译。如果我对共享函数进行了更改,我将不得不重新编译我的主程序。
  2. 将我的共享函数放在一个文件中,并将其编译为共享库(如果我的术语正确的话),并将我的主程序链接到该共享库。我对共享库所做的任何更改(在编译后)都将在运行时集成到我的主程序中,而无需重新编译我的主程序。

我的想法正确吗?

如果是这样,我该如何完成这两种方法中的一种/两种?我进行了很多搜索,似乎找到了如何将自己的程序链接到其他人的共享库的信息,但没有找到如何创建自己的共享函数并以可以在自己的程序中使用它们的方式编译它们的信息.

非常感谢!

布赖恩


编辑:

结论

感谢大家的帮助!我想我会在这篇文章中添加对我有用的东西(对于 AIX 上的动态共享库),以便其他人可以受益:

我编译我的共享函数:

xlc -c sharedFunctions.c -o sharedFunctions.o

然后使其成为共享对象:

xlc -qmkshrobj -qexpfile=exportlist sharedFunctions.o
xlc -G -o libsharedFunctions.so sharedFunctions.o  -bE:exportlist

然后将其链接到另一个程序:

xlc -brtl -o mainProgram mainProgram.c  -L. -lsharedFunctions

另一条评论帮助我找到了这个链接,这也有帮助:http: //publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/proguide/ref/compile_library.htm

再次感谢所有帮助过我的人!

4

3 回答 3

6

是的,你是对的。第一个称为静态库,而第二个称为共享库,因为代码不会在编译时绑定到可执行文件,而是每次加载程序时都会再次绑定。

静态库

编译你的库代码如下:

gcc -c *.c

告诉程序不要链接目标文件,而只是为每个已编译的-c文件留下目标文件。.c现在,将它们归档到一个静态库中:

ar rcs libmystuff.a *.o 

man ar将告诉您 rcs 选项的含义。现在,libmystuff.a 是一个存档文件(您可以使用一些 zip 文件查看器打开它),其中包含这些目标文件以及每个目标文件的符号索引。您可以将其链接到您的程序:

gcc *.c libmystuff.a -o myprogram

现在,您的程序已准备就绪。请注意,静态库在命令中出现的顺序很重要。请参阅我的链接订单答案。

共享库

对于共享库,您将使用

gcc -shared -o libmystuff.so *.c

仅此而已, libmystuff.so现在是一个共享对象文件。如果要将程序链接到它,则必须将其放入文件中列出的目录,或者由切换到 GCC 给出的目录,或者在 LD_LIBRARY_PATH 变量中列出的目录。链接时,您从告诉 gcc 的库名称中删除前缀和后缀。/etc/ld.so.conf-Llib.so

gcc -L. -lmystuff *.c -o myprogram

在内部,gcc 只会将您的参数传递给 GNU 链接器。您可以使用该-###选项查看它传递的参数:Gcc 将打印给每个子进程的确切参数。

有关链接过程的详细信息(某些事情是如何在内部完成的),请查看我的Linux GCC 链接器答案。

于 2009-01-06T20:23:31.327 回答
4

你有第三种选择。通常,您的 C++ 编译器应该能够链接 C 例程。必要的选项可能因编译器而异,因此 R 是您的好 M,但基本上,您应该能够使用 g++ 进行编译,如下所示:

$ g++ -o myapp myapp.cpp myfunc.c giveint.c

...或单独编译

$ gcc -c myfunc.c
$ gcc -c giveint.c
$ g++ -c myapp.cpp
$ g++ -o myapp myapp.o myfunc.o

您还需要包括您的功能声明;你在 C++ 中这样做

extern "C" {
    int myfunc(int,int);
    int giveInterger(void);
}
于 2009-01-06T20:07:04.573 回答
0

您需要区分重新编译和重新链接。

如果您放入giveInteger()一个单独的(存档)库,然后稍后对其进行修改,您将(显然)需要重新编译定义它的源文件,并重新链接所有使用它的程序;但您不需要重新编译此类程序 [1]。

对于共享库,您需要重新编译并重新链接该库;但您不必重新链接或重新编译任何使用它的程序。

在 AIX 上构建 C++ 共享库曾经很复杂;您需要使用 makeC++SharedLib shell 脚本。但是有了 VAC 5.0 和 6.0,它变得非常容易。我相信您需要做的就是[2]:

xlC -G -o shr.o giveInteger.cc
xlC -o myapp main.cc shr.o

[1] 如果您编写正确的 Makefile(这是推荐的做法),所有这一切都会在您键入make.

[2] AIX 的某个特性可能会使事情复杂化:默认情况下,共享库被加载到内存中,并“粘”在那里直到随后重新启动。因此,您可以重建 shr.o,重新运行程序,并观察正在执行的库的“旧”版本。为了防止这种情况发生,一种常见的做法是让 shr.o 不可读:

chmod 0750 shr.o
于 2009-01-07T07:18:16.390 回答