【问题标题】:Calling C functions in main with struct interfaces and additional C files使用结构接口和其他 C 文件在 main 中调用 C 函数
【发布时间】:2018-04-22 18:36:52
【问题描述】:

我已将头文件“msg_queue.h”实现到名为“msg_queue.c”的非主文件中。从这里我创建了一个名为“mq_test.c”的主文件,我创建了一个消息队列并调用了在“msg_queue.c”中实现的函数。然而,当我运行“make”命令时,似乎每个调用的函数都会出现这个错误:

"enqueue", referenced from:
      _main in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [qmsgtest] Error 1

似乎是什么问题,我没有正确实现结构吗?

头文件:

#ifndef MessageQueue_H
#define MessageQueue_H

typedef struct node{
    int data;
    struct node *next;
} Node;

typedef struct {
    Node *front;
    Node *rear;
} MessageQueue;

void enqueue(...); // enqueue
...

#endif //MessageQueue_H

实现头文件的文件:

#include "MessageQueue_H.h"

#ifndef MessageQueue_H
#define MessageQueue_H


/* Interface for integer MQueue */
typedef struct node{
    int data;
    struct node *next;
} Node;

typedef struct {
    Node *front;
    Node *rear;
} MQueue;

void enqueue(... ){ // enqueue

  ....

【问题讨论】:

    标签: c file linker header queue


    【解决方案1】:

    在实现标头msg_queue.c 的文件中,您有一个包含保护:

    #ifndef MSG_QUEUE_H
    #define MSG_QUEUE_H
    

    您在msg_queue.h 中有一个同名的包含保护,并且由于首先预处理标头,因此预处理器删除了实现代码(因为已经定义了MSG_QUEUE_H,您的包含保护正在删除实现代码) ,这就是它找不到符号的原因。

    您可以通过在源代码上运行 gccclang 并使用 -E 选项自行检查。它将向您展示预处理器对您的代码所做的事情(在您的情况下,这意味着您只获得函数的原型,而不是实现)。

    因此您需要删除 .c 源文件中的包含保护。

    值得注意的是,.c 实现文件中通常不需要包含保护,因为这些通常不包含在其他文件中。

    在您的示例中,您还定义了两次结构类型(在标头和 C 文件中)。这违反了单一定义规则,所以如果你想用头文件中的数据类型定义你的接口,你应该从源文件中删除它们,否则它不会编译。

    此代码中还有其他错误会阻止它编译(至少在我测试过的 C99 模式下),但这些与链接器无法找到函数符号的问题无关(s)。

    【讨论】:

    • 此外,我发现方法“printMqueue”中的结构应该声明为“node*”而不是“Node*”。实施这些更正将解决大部分问题并允许程序运行。
    • 是的,您必须通过一致地使用相同的名称来使您的类型的使用与您声明它们的方式相匹配。不管你如何命名它(你可以调用类型Node 并根据需要使用它)。名称必须匹配!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 2013-01-12
    • 2013-03-15
    相关资源
    最近更新 更多