我可以在没有额外编译步骤的情况下定义库所需的 C extern 函数吗?

Can I define a C extern function required by a library without an extra compilation step?

有人向我提供了一个库 a,它期望有一个函数 b() 但没有实现它。看起来像这样(我无法更改此代码):

a.h:

void a();

a.c:

#include "a.h"
extern void b();
void a() {
    b();
}

库是这样编译的(为简单起见,假设这些示例中的所有文件都在同一目录中)。:

gcc -shared a.c -o liba.so

我想在我的代码中调用 a(),所以我编写了一个如下所示的程序:

main_v1.c:

#include "a.h"
int main(void) {
    a();
    return 0;
}

如果我尝试编译它,我会得到一个 linker 错误,因为 b() 尚未定义:

gcc main_v1.c -L ./ -la -o main
.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status

我能做的最简单的事情就是在 main.c:

中添加 b() 的定义

main_v2.c:

#include <stdio.h>
#include "a.h"
void b() {
    printf("b");
}
int main(void) {
    a();
    return 0;
}
gcc main_v2.c -L ./ -la -o main

这行得通。但是,如果我不想在 main.c 中定义 b() 怎么办?例如,如果我希望能够在其他地方重新使用我的 b() 实现?我知道我能做的是将它编译成第二个库并 link 反对它,像这样:

b_v1.c:

#include <stdio.h>
void b() {
    printf("b");
}
gcc -shared b_v1.c -o libb.so
gcc main_v1.c -L ./ -la -lb -o main

这也行。注意-lb 必须在-la之后;反之则不行。

但我真的很想避免编译另一个库。为什么我不能这样做?:

b.h:

void b();

b_v2.c:

#include <stdio.h>
#include "b.h"
void b() {
    printf("b");
}

main_v3.c:

#include "a.h"
#include "b.h"
int main(void) {
    a();
    return 0;
}
gcc main_v3.c -L ./ -la -o main

这行不通。我得到了同样的 linker 错误:

.//liba.so: undefined reference to `b'
collect2: error: ld returned 1 exit status

为什么不呢?这与我在 main_v2.c 中的第一个工作示例有何不同?有没有办法在不为 b() 创建单独的库的情况下完成此操作?

正如 Mat 指出的那样,我只是忽略了在编译步骤中包含 b_v2.c 源代码。这有效:

gcc main_v3.c b_v2.c -L ./ -la -o main

How is this different from my first working example in main_v2.c?

在版本 3 中,甚至没有编译 b() 的实现,更不用说链接到最终的可执行文件中了。仅声明是不够的,包含 header 完全独立于编译或链接关联的源文件。

请注意,您的 a.cmain_v3.cb.h 获取的 b() 声明完全一样多,因此如果 main_v3.c 调用中没有任何内容那个函数,然后 header 没有添加任何新的或有用的东西。

Is there a way to accomplish this without creating a separate library for b()?

当然有,好几个。但最简单的方法可能是在同一个编译命令行上命名两个 C 源文件:

gcc main_v1.c b.c -L. -la -o main

请注意,我有意选择了 main_v1:由于文件中没有任何内容调用 b(),因此该函数的声明直接出现在文件中或通过 header包含。

a.h

void a();

a.c

void b();
void a() {
    b();
}

b.c

#include "a.h"
 #include <unistd.h>
void b()
{
 write(1, "test", 4);
}

编译

$> gcc *.c

执行

$> ./a.out