Ошибка связывания в простой программе на C с использованием заголовка C ++ - PullRequest
3 голосов
/ 27 июля 2011

Я следую вступительному руководству http://www.linuxinsight.com/files/alp/alp-ch01-getting-started.pdf.

Я создал исходные файлы main.c, recerocal.cpp и recerocal.hpp.Я был в состоянии успешно скомпилировать эти файлы.Проблема возникает, когда я иду, чтобы связать их, и я получаю следующее сообщение об ошибке:

main.o: In function `main':
main.c:(.text+0x30): undefined reference to `reciprocal'
collect2: ld returned 1 exit status

Я понимаю, что это почему-то неправильно использует заголовочные файлы, однако я действительно не знаю, что попробовать, поскольку яЯ очень тщательно проделал шаги.

Если у кого-то есть идея, почему она выдает эту ошибку, я был бы очень признателен.

Спасибо

** ОБНОВЛЕНИЕ Воткод для трех исходных файлов:

main.c

#include <stdio.h>
#include "reciprocal.hpp"

int main (int argc, char **argv) {
    int i;
    i = atoi(argv[1]);
    printf("The reciprocal of %d is %g\n", i, reciprocal(i));

    return 0;
}

recerocal.cpp

#include <cassert>
#include "reciprocal.hpp"

double reciprocal(int i) {
    assert(i != 0);
    return 1.0/i;
}

responserocal.hpp

#ifdef __cplusplus
extern "C" {
#endif

double reciprocal(int i);

#ifdef __cplusplus
}
#endif

Iфактически изменили файл responserocal.hpp с момента первоначальной публикации.Единственным изменением, которое я сделал, было удаление ключевого слова extern из сигнатуры функции.Ранее он читал

extern double reciprocal(int i);

Это изменение позволило мне связать программу, и теперь я могу ее запустить.Я думаю, что, возможно, происходило то, что второй экстерьер перекрывал первый.Если у кого-то есть понимание этого, мне было бы интересно узнать.

Спасибо за вашу помощь всем.

Ответы [ 3 ]

5 голосов
/ 27 июля 2011

Когда вы смешиваете код C и C ++ вместе, вы можете столкнуться с проблемами, потому что два языка имеют разные связи .То есть, если бы вы взломали объектные файлы для скомпилированного файла C и C ++, вы обнаружили бы, что имена внутри этих объектных файлов были разными.

В частности, компиляторы C ++ склонны использовать техникуназывается «искажение имени», в котором имена функций смешиваются с дополнительной информацией о типах их аргументов.Например, функция

char foo(int);

может фактически иметь внутреннее имя

char@foo@int

внутри сгенерированного объектного файла.Проблема состоит в том, что код C не делает этого, поэтому, если вы скомпилировали файл C и попытались сделать ссылку на имя foo, компоновщик не найдет его, поскольку имя функции в сгенерированном файле C ++char@foo@int вместо foo.

Чтобы исправить это, в C ++ есть функция, позволяющая явно указать компоновщику не искажать имя и сделать сгенерированный код таким, как он был предназначен дляС программой.Для этого вы можете объявить функции C ++ следующим образом:

extern "C" char foo(int);

Теперь сгенерированный объектный файл будет содержать имя foo без украшения таким образом, чтобы это было совместимо с тем, что ожидает код C.

Чтобы решить вашу проблему, попробуйте добавить одно из этих объявлений extern "C" в ваш исходный файл C ++, который определяет reciprocal.

Примечание: если у вас есть проект, который смешивает код C и C ++Вы должны всегда иметь функцию main, скомпилированную в виде кода C ++.C ++ вводит дополнительный код инициализации и очистки в свои исполняемые файлы, которых нет в C-коде.Если вы компилируете main как код на C, эта дополнительная логика может не добавляться в программу, и поэтому вы можете получить необъяснимые сбои во время выполнения.

Надеюсь, это поможет!

1 голос
/ 27 июля 2011

Похоже, что содержимое вашего reciprocal.hpp недопустимо, возможно, опечатка в строке #ifdef написана __cplusplus правильно (должно быть два подчеркивания)?

1 голос
/ 27 июля 2011

Связать файл C ++ с файлом C в лучшем случае сложно.C ++ «искажает» имя, так что может произойти перегрузка.

Вы можете предотвратить искажение, заключив свое взаимное определение следующим образом:

extern "C" {
   reciprocal definition...
}

, но если вы сделаете это, вы можетену просто напишите это в C ...

Можете ли вы сделать файл main.cpp?

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