如何在C或C ++中获取/链接外部函数?

时间:2009-01-06 19:57:43

标签: c++ c shared-libraries

编辑:我想我应该澄清一下,如果重要的话。我在AIX Unix机器上,所以我使用的是VAC编译器 - 没有gnu编译器。 结束修改


我在C / C ++中相当生疏,所以如果这是一个简单的问题,请原谅我。

我想从一些C程序中获取常用函数,并将它们放在共享库或共享对象中。如果我在perl中这样做,我会将我的潜艇放在perl模块中,并在需要时使用该模块。

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

int giveInteger()
{
    return 1034;
}

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

我很确定我有两个选择:

  1. 将我的共享函数放在一个文件中,并在编译时使用我的主程序进行编译。如果我对共享功能进行了更改,我将不得不重新编译我的主程序。
  2. 将我的共享函数放在一个文件中,并将其编译为共享库(如果我的条款正确),并将我的主程序链接到该共享库。我对共享库所做的任何更改(在编译之后)都会在运行时集成到我的主程序中,而无需重新编译我的主程序。
  3. 我的想法是否正确?

    如果是这样,我怎样才能完成这两种方法中的任何一种/两种方法?我搜索了很多,我似乎找到了如何将自己的程序链接到别人的共享库的信息,但不知道如何创建我自己的共享函数并以我可以在我自己的程序中使用它们的方式编译它们

    非常感谢!

    布赖恩


    编辑:

    结论

    谢谢大家的帮助!我想我会在这篇文章中添加什么对我有用(对于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

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

3 个答案:

答案 0 :(得分:6)

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

静态库

按如下方式编译库的代码:

gcc -c *.c

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

ar rcs libmystuff.a *.o 

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

gcc *.c libmystuff.a -o myprogram

现在,您的程序准备就绪。请注意,静态库在命令中出现的顺序。请参阅我的Link order回答。

共享库

对于共享库,您将使用

创建库
gcc -shared -o libmystuff.so *.c

这就是一切,libmystuff.so现在是 s hared o bject文件。如果要将程序链接到它,则必须将其放入/etc/ld.so.conf文件中列出的目录中,或者由-L切换到GCC,或列在LD_LIBRARY_PATH中的目录中。变量。链接时,您会从您告诉gcc的库名称中删除lib前缀和.so后缀。

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

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

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

答案 1 :(得分: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);
}

答案 2 :(得分: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