【问题标题】:Linking another library from C-library in gwan/libraries results in "undefined symbol" error在 gwan/libraries 中从 C 库链接另一个库会导致“未定义符号”错误
【发布时间】:2016-09-10 10:58:37
【问题描述】:

我正在尝试在我的 C 库文件 my_uuid.c 中使用标准库 libuuid:

gwan/libraries/my_uuid.c:

#include <uuid/uuid.h>
#pragma link "uuid"
void my_uuid_generate(uuid_t uuid)
{
  uuid_generate(uuid);
}

gwan/init.c:

#include <uuid/uuid.h>
#pragma link "uuid"
#pragma link "libraries/my_uuid.c"
int main(int argc, char *argv[])
{
  uuid_t uuid;
  my_uuid_generate(uuid);
  return 0;
}

但是,G-Wan 无法启动并打印这样的消息:

链接./init.c:未定义符号:uuid_generate

这一定不是 libuuid 安装或非标准路径的问题,因为这样的 servlet 确实可以成功:

#include <uuid/uuid.h>
#pragma link "uuid"
int main(int argc, char *argv[])
{
   uuid_t uuid;
   char str[256];

   uuid_generate(uuid);
   uuid_unparse(uuid, str);
   printf("%s\n", str);

   xbuf_cat(get_reply(argv), "Hello, World!");
   return 200;
}

问题可能是由于 G-Wan 先加载 init.c 然后再加载 my_uuid.c 而不是 libuuid,即使我在 init.c 中有 #pragma link "uuid"。

有人知道如何解决这个问题吗? 从 gwan/libraries 中的 C 文件库链接其他库是否有效?

【问题讨论】:

  • “C 文件库”,正如您所说的那样,它们并不是使用 G-WAN 的预期方式,因此我的回复如下。此外,动态链接有开销(内存、缓存行、CPU 缓存),这意味着您应该只将它用于大型库,其大小将取消直接链接的目标代码的资格,因为如果多个 G-WAN 脚本使用它可能会重复。跨度>

标签: g-wan


【解决方案1】:

我阅读了 GWAN 的文档。如果您编写自己的库,您应该能够很好地与它集成(将其视为预先存在的库)。

myuuid.h
myuuid.c

然后通过编译 myuuid.c 来生成你的库:

libmyuuid.a

将库作为 gwan/libraries/libuuid.a 并尝试如下。

#include "myuuid.h"
#pragma link "./libraries/myuuid"

int main(int argc, char *argv[])
{
    my_uuid_generate();
    return 0;
}

您可能需要密切关注 gwan/logs/gwan.log 文件以查看链接是否有效。您也可以在终端中手动启动 GWAN 服务器以查看错误。

【讨论】:

  • 谢谢,但不幸的是,它也只有在我将 #pragma link "uuid" 放在 init.c 文件的末尾时才有效(类似于我上一个答案),否则它会失败并出现相同的错误“链接./init.c: 未定义符号:uuid_generate"。
【解决方案2】:

servlet 有效,因为您将脚本直接链接到现有库(已编译的代码)。

init.c 脚本无法链接,因为调用已编译库的 "#pragma link "libraries/my_uuid.c" 库尚不存在(它仍然是源代码)。

您应该在init.c 中使用#include "libraries/my_uuid.c" 来让这种构造工作。

【讨论】:

  • 如果 my_uuid.c 还没有作为二进制文件存在,我希望 init.c 在 my_uuid_generate() 上失败,但在 uuid_generate() 上失败 - 这应该意味着 my_uuid.c 有被翻译成二进制库。我对吗?如果我错了,链接器如何知道来自 not-yet-translated-into-binary my_uuid.c 的 uuid_generate() 调用?
【解决方案3】:

有趣的是,当我在 init.c 文件中将 #pragma link "uuid" 移动到 #pragma link "libraries/my_uuid.c" 下方时,G-Wan 成功启动:

#include <uuid/uuid.h>
#pragma link "libraries/my_uuid.c"
#pragma link "uuid"
int main(int argc, char *argv[])
{
  uuid_t uuid;
  my_uuid_generate(uuid);
  return 0;
}

毫无疑问,它改变了 G-Wan 加载 libuuid 和 my_uuid.c 的顺序。现在它首先加载 libuuid(带有 uuid_generate() 符号),然后加载 my_uuid.c(带有 my_uuid_generate() 符号,然后调用 uuid_generate())。

Gil,我是否正确理解当前 G-Wan 的设计目的不是提供可控制的库加载顺序? G-Wan 团队是否可以考虑更新 G-Wan 服务器以以可控/可预测的顺序加载库,至少在某种程度上? IE。在依赖用户之前加载依赖。 例如我们应该可以编写如下代码,G-Wan 服务器首先加载 libuuid,然后是 my_uuid.c,然后是 init.c:

gwan/libraries/my_uuid.c:

#pragma link "uuid"

gwan/init.c:

#pragma link "libraries/my_uuid.c"

(注意 init.c 中没有 #pragma 链接“uuid”)

【讨论】:

  • 我认为 GWAN 对库的加载(或其顺序)没有太多控制。它只是将“.C”文件交给编译器/链接器(单独或一起取决于操作系统/环境和其他因素)。编译器提取编译指示/链接器选项并将它们插入到链接器的命令行中。
  • 他们网站上给出的curl example 没有提及将引导代码放入 init.c 文件中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
  • 2021-07-08
  • 1970-01-01
  • 2012-01-19
  • 2019-02-21
相关资源
最近更新 更多