C Code Link Errors with an iPhone App
Question: I am having link errors when integrating a small number of C source files into
an objective-c iOS project.

The C files were given to me by another developer who successfully used the
code in c projects and in python projects.

When I add the c source code into the XCode project, the code compiles, but I
get link errors after adding code in the objective c files to reference to C
code. I get "duplicate symbol errors" for variables in the C code. This is
when the objective c code has the .m extension.

When I change the objective c file to the .mm extension, I get "symbols not
found for architecture i386" errors for the C functions I am calling from the
objective c code.

There are many questions about C and objective C on forums, and I haven't
found a solution yet. Any quick things to check?

Code snippets:

    
    
    File: res.h
    
    float Max_Std_Amp = 50;
    void RD_Dispose(void);
    
    File: res.c
    void RD_Dispose(void) {
       Max_Std_Amp = 0;
    }
    
    
    File: Import.mm
    #import "res.h"
    void process(UInt32* data, UInt32 dataLength)
    {
        RD_Dispose();
    }
    

Link errors:

When Import.m has a .m extension:

    
    
    duplicate symbol _Max_Std_Amp in:
        /Users/dayhacker/Library/Developer/Xcode/DerivedData/My_Project-dbvpktweqzliaefgbqbebtdgyrey/Build/Intermediates/My Project.build/Debug-iphonesimulator/Respitory Rate.build/Objects-normal/i386/Import.o
    

When Import.mm has a .mm extension:

    
    
    Undefined symbols for architecture i386:
     "RD_Dispose()", referenced from:
     process(unsigned long*, unsigned long) in Import.o
    


Answer: res.h:

    
    
    float Max_Std_Amp = 50;
    

That should be:

    
    
    extern float Max_Std_Amp;
    

and the actual `float` defined in a source file (`res.c`):

    
    
    float Max_Std_Amp = 50;
    

Otherwise `Max_Std_Amp` will be part of every source module that includes
`res.h`, which is not what was intended.

If you want to use a C-function from C++ (`.mm` is Objective-C++), you need to
declare the function as having C-linkage, like this:

res.h:

    
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void RD_Dispose(void);
    
    #ifdef __cplusplus
    }  // extern "C"
    #endif
    

The above use of guard macros and C-linkage definition will allow the `res.h`
header file to be included in both C and C++ (Objective-C and Objective-C++)
source modules.

