我可以在没有额外编译步骤的情况下定义库所需的 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.c
与 main_v3.c
从 b.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
有人向我提供了一个库 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.c
与 main_v3.c
从 b.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