这是一道关于C/C++函数定义的题。讨论的代码是 static 库 libRmath
,它在 R
的 Rmath.h
头文件中提供定义。
为库提供的 documentation 表明用户可以选择为函数 double unif_rand(void)
提供函数定义。
所以我的问题是,如果这样的函数定义是可选的,会不会出现C/C++
中不允许的多个函数定义的问题?
编辑: 在不查看源代码的情况下推测事情是如何工作的可能很诱人,但这不是我想要的。我很想知道它真正 是如何工作的,因此您可能需要阅读 source code 和 documentations 才能回答这个问题。
最佳答案
当您的应用程序被链接时,未解析的符号将使用您提供的库进行解析。如果您不定义函数,它将在链接期间成为未解析的符号,因此,在这种情况下,链接将尝试使用 librmath 解析该符号。如果无法解析一个或多个符号,您将收到链接器错误。
但是,如果您确实在代码中定义了该函数,那么它将在链接期间已经定义,因此无需使用来自外部库的符号来解析它。
您不能做的是在您的应用程序中多次定义相同的符号。
编辑:由于在另一个答案中有很多争论,我做了一个实际的例子。我创建了一个共享对象(类似于 Windows 中的 DLL),它定义并导出了一个函数 foo
:
//lib.h
extern "C" {
void foo();
void bar();
};
//lib.cpp
#include <iostream>
#include "lib.h"
void foo() {
std::cout << "From lib\n";
}
void bar() {
std::cout << "Bar, calling foo\n";
foo();
}
为了测试这个共享对象,我创建了一个与之链接的应用程序:
//test.cpp
#include <iostream>
#include "lib.h"
void foo() {
std::cout << "From app\n";
}
int main() {
bar();
}
我已经编译了共享对象和应用程序:
g++ lib.cpp -o libtest.so -Wall -fPIC -shared -Wl,--export-dynamic -Wl,-soname,libtest.so -Wl,-z,defs
g++ test.cpp -o test -L. -ltest
当我执行 test
时,将库路径设置为 "."
,这样我的共享对象就可以加载了,我得到了这个输出:
matias@master:/tmp$ LD_LIBRARY_PATH="." ./test
Bar, calling foo
From app
如您所见,调用了应用程序(而非共享对象)中定义的foo
函数。您基本上可以为共享对象中的每个导出符号执行此操作。
EDIT2:我在 lib.h 中添加了另一个导出函数。应用程序现在调用此函数,最终调用 foo。结果与预期相同。
EDIT3:好的,让我们更深入一点。这是函数 bar
的转储:
Dump of assembler code for function bar@plt:
0x0804855c <+0>: jmp DWORD PTR ds:0x804a004
0x08048562 <+6>: push 0x8
0x08048567 <+11>: jmp 0x804853c
如果我们转到地址 0x804a004
:
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
0x08049ff4 <+0>: or BYTE PTR [edi+0x804],bl
0x08049ffa <+6>: add BYTE PTR [eax],al
0x08049ffc <+8>: add BYTE PTR [eax],al
0x08049ffe <+10>: add BYTE PTR [eax],al
.....
如您所见,它正在跳转到全局偏移表。您可以阅读 GOT here和 here .动态符号(在运行时解析)存储在该表中。每当你调用一个应该在运行时解析的符号时,你实际上是跳转到这张表,然后跳转到存储在这张表对应表项中的地址。由于应用程序定义了 foo
,因此 GOT 包含来自 test.cpp
的定义地址,而不是我们共享对象中的地址。
EDIT4:好的,最后编辑。引用文档:
You will need to supply the uniform random number generator
double unif_rand(void)
or use the one supplied (and with a dynamic library or DLL you will have to use the one supplied(...)
文档明确指出,如果您使用的是动态库,则不能提供您自己的 unif_rand
实现。因此,我相信我所指出的实际上回答了您的问题。
关于c++ - C/C++ 代码中函数的多重定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9882089/