Как включить файл только один раз / Предотвратить переопределения функций в старом C API из C ++ Program

0

У меня есть программа C++, которая должна использовать API на основе C для конкретной задачи. Если я включу только в один cpp в моей программе, у меня проблем нет. Однако, если я включаю в заголовочный файл (где мне нужно использовать некоторые типы), я получаю ошибки редизайна компоновщиком.

Это связано с множеством typedefs, сделанных в заголовке внешних библиотек (заголовок C с компилированным dll). Я ищу любые возможные решения этой проблемы.

Когда я ищу все, что я могу найти, это элемент защиты заголовка (и #pragma один раз), но это не решение проблемы, поскольку то, что я нахожу, - это несколько определений в отдельных единицах компиляции, которые затем конфликтуют при связывании.

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

Output for building on Warning Level 4
Warning 1   warning C4273: 'getwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  615 1   project-test
Warning 2   warning C4273: 'putwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  617 1   project-test
Warning 3   warning C4273: 'getwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  615 1   project-test
Warning 4   warning C4273: 'putwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  617 1   project-test
Warning 5   warning C4100: 'data' : unreferenced formal parameter   c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 6   warning C4100: 'event' : unreferenced formal parameter  c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 7   warning C4100: 'widget' : unreferenced formal parameter c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 8   warning C4100: 'data' : unreferenced formal parameter   c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 9   warning C4100: 'event' : unreferenced formal parameter  c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 10  warning C4100: 'widget' : unreferenced formal parameter c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 11  warning C4505: 'g_bit_nth_lsf' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   267 1   project-test
Warning 12  warning C4505: 'g_bit_nth_msf' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   269 1   project-test
Warning 13  warning C4505: 'g_bit_storage' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   271 1   project-test
Warning 14  warning C4505: 'g_string_append_c_inline' : unreferenced local function has been removed    c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gstring.h  130 1   project-test
Warning 15  warning C4505: 'g_trash_stack_push' : unreferenced local function has been removed  c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  44  1   project-test
Warning 16  warning C4505: 'g_trash_stack_pop' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  46  1   project-test
Warning 17  warning C4505: 'g_trash_stack_peek' : unreferenced local function has been removed  c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  47  1   project-test
Warning 18  warning C4505: 'g_trash_stack_height' : unreferenced local function has been removed    c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  48  1   project-test
Error   19  error LNK2005: "long __cdecl abs(long)" (?abs@@YAJJ@Z) already defined in FitsFile.obj  C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   20  error LNK2005: "__int64 __cdecl abs(__int64)" (?abs@@YA_J_J@Z) already defined in FitsFile.obj  C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   21  error LNK2005: "struct _ldiv_t __cdecl div(long,long)" (?div@@YA?AU_ldiv_t@@JJ@Z) already defined in FitsFile.obj   C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   22  error LNK2005: "struct _lldiv_t __cdecl div(__int64,__int64)" (?div@@YA?AU_lldiv_t@@_J0@Z) already defined in FitsFile.obj  C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   23  error LNK2005: _getwchar already defined in FitsFile.obj    C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   24  error LNK2005: _putwchar already defined in FitsFile.obj    C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\project-test\main.obj  project-test
Error   25  error LNK1169: one or more multiply defined symbols found   C:\Users\Ian\SkyDrive\Documents\Uni\FINPRO\projects\project-test\Debug\project-test.exe project-test

Изображение 174551

Output for building on Warning Level 4 (when only including for one place)
Warning 1   warning C4273: 'getwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  615 1   project-test
Warning 2   warning C4273: 'putwchar' : inconsistent dll linkage    c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h  617 1   project-test
Warning 3   warning C4100: 'data' : unreferenced formal parameter   c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 4   warning C4100: 'event' : unreferenced formal parameter  c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 5   warning C4100: 'widget' : unreferenced formal parameter c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  8   1   project-test
Warning 6   warning C4100: 'data' : unreferenced formal parameter   c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 7   warning C4100: 'event' : unreferenced formal parameter  c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 8   warning C4100: 'widget' : unreferenced formal parameter c:\users\ian\skydrive\documents\uni\finpro\projects\project-test\project-test\main.cpp  15  1   project-test
Warning 9   warning C4505: 'g_bit_nth_lsf' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   267 1   project-test
Warning 10  warning C4505: 'g_bit_nth_msf' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   269 1   project-test
Warning 11  warning C4505: 'g_bit_storage' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gutils.h   271 1   project-test
Warning 12  warning C4505: 'g_string_append_c_inline' : unreferenced local function has been removed    c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gstring.h  130 1   project-test
Warning 13  warning C4505: 'g_trash_stack_push' : unreferenced local function has been removed  c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  44  1   project-test
Warning 14  warning C4505: 'g_trash_stack_pop' : unreferenced local function has been removed   c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  46  1   project-test
Warning 15  warning C4505: 'g_trash_stack_peek' : unreferenced local function has been removed  c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  47  1   project-test
Warning 16  warning C4505: 'g_trash_stack_height' : unreferenced local function has been removed    c:\users\ian\skydrive\documents\uni\finpro\gtk\include\glib-2.0\glib\gtrashstack.h  48  1   project-test

Изображение 174551

  • 4
    Похоже, этот C "API" не очень похож на API, если у вас так много проблем с использованием. Есть подробные инструкции или что-нибудь по использованию?
  • 3
    typedefs являются проблемой, только если файл включен дважды для одного и того же объектного файла. Переопределение на этапе компоновщика связано с определением переменных, поэтому вам нужно предоставить больше информации о заголовке и точных ошибках
Показать ещё 20 комментариев
Теги:
visual-studio
visual-c++

3 ответа

2
Лучший ответ

Аннотация Функциональность C за слоем косвенности:

оригинальная структура (если я правильно понимаю, это то, что у вас есть):

file1.h -> #include included_c_api.h
file2.h -> #include included_c_api.h CAUSES errors.

новая структура:

new_c_api.h -> wrapper over included_c_api.h functionality (w/ your own symbols)
new_c_api.c[pp] -> #include included_c_api.h
file1.h -> #include new_c_api.h
file2.h -> #include new_c_api.h

Если функциональность, представленная в include_c_api.h, очень велика, это решение может быть непрактичным.

  • 0
    Насколько я могу судить по моим исследованиям и приведенным выше комментариям, это единственное реальное решение, которое у меня есть. Это гарантирует, что файл включен только один раз за слой косвенности.
  • 0
    Таким образом удаляет ошибки из компилятора и гарантирует, что он может быть использован. Смотрите комментарии по вопросу для дальнейшего объяснения.
0

Вы не говорите, если проблема связана с переменными или функциями. У них разные решения:

переменные: заголовочный файл должен иметь декларацию "extern" для переменной, только с одним "C" файлом, содержащим определение (то же, что и декларация extern, но без слова extern спереди).

функции: это происходит только тогда, когда у вас есть тела функций в заголовках - в этом случае вы должны поставить "inline" перед определением функции, чтобы код функции был встроен в каждый объектный модуль, который его использует, а компоновщик не использует ' t иметь дело с этим на всех. Прототипы функций не будут вызывать повторяющиеся ошибки определения.

При связывании кода C и кода C++ вам также необходимо получить правильное название, что в основном означает, что вы должны окружать все объявления, которые применяются к объектам "C", со следующим кодом при компиляции этих объявлений с помощью C++ компилятор:

extern "C" { 

... 'C' declarations

}

Вы обычно видите

#if defined(__cplusplus)
extern "C" { 
#endif 

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

0

Ищите две вещи:

a) Вы не используете защитные устройства. Как правило, все заголовки должны иметь следующую структуру. Это гарантирует, что только одна копия заголовка включена в файл C++.

#ifndef MYPROJECT_DIR_FILE_H
#define MYPROJECT_DIR_FILE_H

... all declarations and definitions ...

#endif

b) Убедитесь, что все функции, определенные в заголовке, являются встроенными. В противном случае несколько файлов C++ будут иметь копии той же функции, которые путают компоновщик. inline просит отменить все, кроме одного экземпляра функции.

  • 0
    inline не запрашивает отбрасывание, он заставляет функцию быть встроенной в собственный код этого объектного модуля, так что компоновщик его вообще не видит.
  • 0
    Неверно: inline функции все еще можно использовать odr, что приводит к включению регулярного определения. В любом случае, компилятор свободен игнорировать inline любом случае.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню