Search code examples
objective-cxcodeobjective-c++

How to share a global function between .m file and .mm file (obj c and obj c++) with common header file?


abc.h

/**
 @function  GetInputSizeFromUsage
 @abstract  return frame width and height from usage
 @param     usage   PPVEUsage to be inqure
 @param     width   (out) the input width for usage
 @param     height  (out) the input height for usage
 */
void GetInputSizeFromUsage(PPVEUsage usage, size_t *width, size_t *height);

file1.m

#import <abc.h>
void GetInputSizeFromUsage(PPVEUsage usage, size_t *width, size_t *height)
{
    switch(usage) {
        case UsageLandscape848x480:
            *width = 848;
            *height = 480;
            break;

        default:
            *width = 0;
            *height = 0;
            break;
    }

}

// This file uses this above function in various other functions and is fine to compile

file2.mm

#import <abc.h>

size_t GetInputSizeFromUsage(PPVEUsage usage)
{
    size_t width, height;
    GetInputSizeFromUsage(usage, &width, &height);
    return (width * height);
}

Error: Undefined symbol: GetInputSizeFromUsage(PPVEUsage, unsigned long*, unsigned long*)

The error is due to file2.mm not being able to see the symbol. If I comment it out in file2.mm it compiles fine.

Expecting it to be able to see the symbols


Solution

  • Objective-C++ is superset of C++ language and all rules of C++ apply here. I.e. when declaring a function you have to deal with so-called name mangling, which alters the function signature in a way that the compiler won't be able to locate it in a Objective-C/C compilation unit. For such scenarios you are supposed to tell the linker to apply C rules when including this header in a C++ compilation unit by employing extern "C" section:

    #ifdef __cplusplus
    extern "C" {
    #endif
    void GetInputSizeFromUsage(PPVEUsage usage, size_t *width, size_t *height);
    #ifdef __cplusplus
    }
    #endif