У меня есть программа 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
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
Аннотация Функциональность 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, очень велика, это решение может быть непрактичным.
Вы не говорите, если проблема связана с переменными или функциями. У них разные решения:
переменные: заголовочный файл должен иметь декларацию "extern" для переменной, только с одним "C" файлом, содержащим определение (то же, что и декларация extern, но без слова extern спереди).
функции: это происходит только тогда, когда у вас есть тела функций в заголовках - в этом случае вы должны поставить "inline" перед определением функции, чтобы код функции был встроен в каждый объектный модуль, который его использует, а компоновщик не использует ' t иметь дело с этим на всех. Прототипы функций не будут вызывать повторяющиеся ошибки определения.
При связывании кода C и кода C++ вам также необходимо получить правильное название, что в основном означает, что вы должны окружать все объявления, которые применяются к объектам "C", со следующим кодом при компиляции этих объявлений с помощью C++ компилятор:
extern "C" {
... 'C' declarations
}
Вы обычно видите
#if defined(__cplusplus)
extern "C" {
#endif
в верхней части заголовочных файлов (аналогичный код внизу), которые были разработаны для включения в файлы C и C++. Это хорошо освещено здесь - но это не похоже на то, что у вас в настоящее время проблема с изменением имени, хотя я ожидаю, что вы до того, как проект закончится...
Ищите две вещи:
a) Вы не используете защитные устройства. Как правило, все заголовки должны иметь следующую структуру. Это гарантирует, что только одна копия заголовка включена в файл C++.
#ifndef MYPROJECT_DIR_FILE_H
#define MYPROJECT_DIR_FILE_H
... all declarations and definitions ...
#endif
b) Убедитесь, что все функции, определенные в заголовке, являются встроенными. В противном случае несколько файлов C++ будут иметь копии той же функции, которые путают компоновщик. inline
просит отменить все, кроме одного экземпляра функции.
inline
не запрашивает отбрасывание, он заставляет функцию быть встроенной в собственный код этого объектного модуля, так что компоновщик его вообще не видит.
inline
функции все еще можно использовать odr, что приводит к включению регулярного определения. В любом случае, компилятор свободен игнорировать inline
любом случае.