Ошибка компоновщика при попытке реализовать инкапсуляцию в C - PullRequest
0 голосов
/ 16 октября 2019

Рассмотрим эти файлы:

obj.h

#pragma once
struct obj;

int obj_size(void);
void obj_set_id(struct obj*, int);
int get_obj_id(struct obj*);

obj.c

#include "obj.h"


struct obj
{
    int id;
};

int obj_size(void) {
    return sizeof(struct obj);
}

void obj_setid(struct obj* o, int i) {
    o->id = i;
}

int obj_getid(struct obj* o) {
    return o->id;
}

main.c

#include <stdio.h>
#include "obj.c"

int main()
{
    puts("hello world");
}

Asоказывается, это способ реализации инкапсуляции в C (https://en.wikipedia.org/wiki/Opaque_pointer#C). Однако, когда я пытаюсь скомпилировать, я получаю ошибку компоновщика. Это жалобы Visual Studio:

Ошибка LNK2005_obj_getid уже определено в obj.obj
Ошибка LNK2005 _obj_setid уже определено в obj.obj
Ошибка LNK2005 _obj_size уже определено в obj.obj
Ошибка LNK1169 найден один или несколько кратно определенных символов

Он настроен на компиляцию кода на C, если кому-то интересно.

Это ошибки, которые я получаю, когда пытаюсь скомпилировать его с помощью clang:

 clang-7 -pthread -lm -o main main.c obj.c
/tmp/obj-36b460.o: In function `obj_getid':
obj.c:(.text+0x30): multiple definition of `obj_getid'
/tmp/main-a2c3dc.o:main.c:(.text+0x30): first defined here
/tmp/obj-36b460.o: In function `obj_setid':
obj.c:(.text+0x10): multiple definition of `obj_setid'
/tmp/main-a2c3dc.o:main.c:(.text+0x10): first defined here
/tmp/obj-36b460.o: In function `obj_size':
obj.c:(.text+0x0): multiple definition of `obj_size'
/tmp/main-a2c3dc.o:main.c:(.text+0x0): first defined here
/tmp/main-a2c3dc.o: In function `main':
main.c:(.text+0x59): undefined reference to `obj_set_id'
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)
compiler exit status 1

Я пытался extern-ing объявления функций в obj.h, но это тоже не сработало. То же самое для inline -ing их.

1 Ответ

1 голос
/ 16 октября 2019

Отвечая на ваш вопрос в его текущем состоянии:

Ваша ошибка состоит в том, чтобы включить «obj.c» вместо «obj.h».

#include Директива работает (кратко), например, если содержимое названного файла заменяет директиву.

Если вы компилируете "main.c" и "obj.c", вы даете все в "obj.c"дважды компоновщику. Вот почему он выдает ошибку.


Вы можете отредактировать свой вопрос, чтобы обновить его, если у вас есть новая информация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...