【问题标题】:Why do we link the curl library even after including it as a header file?为什么即使将 curl 库作为头文件包含在内,我们还要链接它?
【发布时间】:2021-03-07 11:27:07
【问题描述】:
#include <curl/curl.h>

int main()
{
    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com")
    return 0;
}

编译时:

gcc foo.c -lcurl

如果不包含 curl 库,为什么会返回此错误?:

/usr/bin/ld: /tmp/cclp7KeN.o: in function `main':
foo.c:(.text+0x157): undefined reference to `curl_easy_init'
/usr/bin/ld: foo.c:(.text+0x17f): undefined reference to `curl_easy_setopt'
collect2: error: ld returned 1 exit status

提前致谢。

【问题讨论】:

  • 完成工作(卷曲、打印、扫描、数学等)所需的代码不是由核心语言编写或指定的。该代码由编译器编写者(更准确地说:库编写者)编写。他们编写代码、编译代码并将输出(处理器/操作系统的可执行指令)添加到库中。然后,您必须包含该特定库才能创建具有所需功能的可执行文件。添加#include ... 只是文本,只是告诉编译器如何与库中已有的代码交互的信息。默认情况下,libc 会自动包含在内。

标签: c curl libcurl


【解决方案1】:

您包含声明(#define、enum、union、struct、union、typedef 和函数签名),但在定义中链接(实现;已经为您编译的库)。对于您在int main(); 上面发布的代码将是声明,它是一个函数签名,不会按原样执行任何操作,int main() { ... } 是您的定义。

【讨论】:

  • 所以包含头文件就像为main下面的函数编写原型一样。对吗?
【解决方案2】:

在源文件中包含头文件告诉编译器从哪里获取 curl 库中函数和对象的声明。

在命令行中包含库文件会告诉链接器从何处获取包含 curl 库中函数和对象定义的对象模块。

gcc 命令本身不进行编译或链接。它调用其他可执行文件来执行这些和/或其他功能,并且它执行的操作取决于传递给它的开关和参数。)

【讨论】:

  • 所以包含标题就像为main下面的函数编写原型一样。对吗?
  • @a_coder:包括标题包括该文件的内容,就好像它们已写入源文件一样。声明不必低于main。事实上,标识符的声明必须出现在标识符被使用之前。许多人将定义(函数的声明如果包含函数的代码就是定义)放在main 之后,将非定义声明(没有代码的声明)放在main 之前,但没有要求这样做。你把函数的定义放在main上面。
  • 头文件只是c源代码,你会看到curl/easy.h有CURL_EXTERN CURL *curl_easy_init(void);CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);这两行
【解决方案3】:

标头仅包含宏定义、类型定义和函数声明之类的内容 - 它不包含库的实际源代码。

库的代码已经编译并打包在一个单独的二进制文件中,可以静态链接到您的程序或在运行时加载(取决于您的需要)。

将标头视为定义库的接口 - 您仍然需要链接到它的实现

【讨论】:

    猜你喜欢
    • 2019-06-04
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多