Question

I have a C++ program that HAS to use a C based API for a specific task. If I include only in to a single cpp in my program I have no problems at all. However if I include in to a header file (where I need to use some types) I get redefinition errors by the linker.

This is due to a number of typedefs made in the external libraries (C header with compiled dll) header. I am looking for any possible solutions to this problem.

When I search all I can seem to find is header guard stuff (and #pragma once) but these aren't the solution to the problem as what I am finding is multiple definitions in separate compilation units that are then conflicting whilst linking.

I was thinking about extern but found that I am unable to use any types defined in the header as members in a C++ class, which is mostly what I am trying to do.

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 on warning level 4

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

enter image description here

Was it helpful?

Solution

Abstract the C functionality behind a layer of indirection:

original structure (if I understand correctly this is what you have now):

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

new structure:

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

If the functionality exposed in included_c_api.h is very big, this solution could be impractical.

OTHER TIPS

Look for two things:

a) You don't use include guards. As a general rule, all your headers should have the following structure. This ensures that only a single copy of a header is included into a C++ file.

#ifndef MYPROJECT_DIR_FILE_H
#define MYPROJECT_DIR_FILE_H

... all declarations and definitions ...

#endif

b) Make sure all functions that are defined in a header are inline. Otherwise, multiple C++ files will have copies of the same function which will confuse the linker. inline requests to discard all except one copies of the function.

You don't say if the problem is with variables or functions. They have different solutions:

variables: the header file must have an 'extern' declaration for a variable, with just one 'C' file containing a definition (same as the extern declaration, but without the word extern in front).

functions: this only happens when you have function bodies in the headers - in which case you should put 'inline' in front of the function definition, so that the function code is embedded into each object module which uses it, and the linker doesn't have to deal with it at all. Function prototypes will not cause duplicate definition errors.

When linking C code and C++ code, you also need to get the name mangling right - which basically means you should surround all the declarations which apply to 'C' objects with the following code when you compile those declarations with a C++ compiler:

extern "C" { 

... 'C' declarations

}

You usually see

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

at the top of header files (an similar code at the bottom) which have been designed to be included in both C and C++ files. This is well covered here - but it doesn't sound like you currently have a name mangling problem, though I expect you will before the project's finished...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top