26

I've got a weird linker issue. I have code that looks like so:

    double given_amount = self.modelController.levelCompleteRewardAmount;
    swrve_currency_given(swrve, (CFStringRef)@"currencyName", given_amount);

I have this code in two separate places: In an objective-c and an objective-c++ file. It compiles fine in objective-C land, but the swrve_currency_given() function causes the following in my WGController.mm file:

Undefined symbols for architecture armv7:
  "swrve_currency_given(Swrve*, __CFString const*, double)", referenced from:
      -[WGController giveTheUserSomeCashForPlayingThisLevel] in WGController.o
ld: symbol(s) not found for architecture armv7
collect2: ld returned 1 exit status

I'm not entirely sure if this error is related to the Obj-C vs. C++ thing, but it feels like it. My theory is that it perhaps thinks that it is a function on the Obj-C class? The 'swrve' code is 3rd party code, one .h and .c file and I'm importing like so:

#import "swrve.h"

Any help is appreciated! Thanks

Chris Hill
  • 1,914
  • 1
  • 16
  • 24
  • Are you also importing it in the project for the linker? Go to the properties of your target, and open "Linked Frameworks and Libraries" on the summary page. The `swrve` library should be there; if it is not, add it and try compiling again. – Sergey Kalinichenko Feb 17 '12 at 20:07
  • The library isn't a static lib/framework, it is just a .c and .h file. (i have updated my question to reflect that). – Chris Hill Feb 17 '12 at 20:19

2 Answers2

48

You may need to surround the function prototype with:

#if defined __cplusplus
extern "C" {
#endif

void swrve_currency_given (...whatever goes here...);

#if defined __cplusplus
};
#endif

That tells the compiler that it's a C function and not a C++ function.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • Looks like it worked, but boy that's a lot of boiler plate to add! Thanks! – Chris Hill Feb 17 '12 at 20:24
  • I've added a variant using the `extern "C"` syntax variant without block scope, which I find somewhat cleaner as you only have to do the boilerplate stuff once. It was a bit too big for a comment, but the edit should hopefully be approved soon. – pmdj Feb 19 '12 at 12:21
  • To clarify the answer for posterity: you add this code to the .h file for the c code. – Winston Du Aug 27 '20 at 06:03
9

If you are using c function in c++ file. you should use extern "c"{}. In .h file

#ifdef __cplusplus
extern "C" {
#endif

swrve_currency_given(parameter1, parameter2, parameter3);// a c function


#ifdef __cplusplus
}
#endif  

extern "C" is meant to be recognized by a C++ compiler and to notify the compiler that the noted function is (or to be) compiled in C style.

If you're linking to a library that was compiled as C code. use

extern "C" {
  #include "c_only_header.h"
}

Take a look at When to use extern "C" in C++?

Community
  • 1
  • 1
Parag Bafna
  • 22,812
  • 8
  • 71
  • 144