Linker error calling C-Function from Objective-C++ - objective-c

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

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.

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++?

Related

Header file inclusion doesn't work in MPLAB X IDE

screenshot of my code and error data
This is my main.c file
#include "services_initialisations_prototype.h"
#include "services_functions_prototype.h"
void main(void)
{
initSfr();
while(1){
updateMatrix(404, 1);
}
return;
}
this is my services_initialisations_prototype.h
#ifndef XC_HEADER_TEMPLATE_H
#define XC_HEADER_TEMPLATE_H
#include <xc.h> // include processor files - each processor file is guarded.
#include <stdint.h>
//these are my function declarations
extern void initInterrupt();
extern void initIoc();
extern void initAdc();
extern void initTimer2();
extern void initSfr();
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XC_HEADER_TEMPLATE_H */
this is my services_functions_prototype.h
#ifndef XC_HEADER_TEMPLATE_H
#define XC_HEADER_TEMPLATE_H
#include <xc.h> // include processor files - each processor file is guarded.
#include <stdint.h>
//these are my function declarations
extern void updateMatrix(int, int);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XC_HEADER_TEMPLATE_H */
When I try to include two header files in MPLAB X IDE version 4.05, it seems like it is not identifying the second header file. i tried swapping the order, but still the second one is not detected.
The services_initialisation_prototype.h contains initialisations of SFRs and services_functions_prototype.h contains prototypes of other functions. these functions are independent of each other.
when i compile, it is showing that
function updateMatrix() is declared as implicit int.
conflicting declarations for variable _updateMatrix()
which shows that the header file services_functions_prototype is not identified.
the screenshot attached shows the code in services_functions_prototype.h in grey color, and it seems that part of code is not executed.
When I copied the whole declarations from header file to my main file, it is working perfectly fine.
You used the same include guard in both files. Because one file is included before the other, it defines XC_HEADER_TEMPLATE_H which makes #ifndef fail in the second file. Change them to something unique. Wiki include guard.
Remember that identifiers with two leading underscores or identifiers with a leading underscore and an upper case letter are reserved by C standard. Good documentation online is in gcc reserved names.
Use filename with uppercase like SERVICES_FUNCTIONS_PROTOTYPE_H_ and SERVICES_INITIALIZATIONS_PROTOTYPE_H_.
Notes:
Empty parameter list in function declaration declares a function that takes unknown count and type of parameters. Prefer explicitly writing void inside function parameter list to define a function that takes no argument, to enable compiler static checking. Ie. do void initInterrupt(void);. cppreference function declaration
Identifiers declared at file scope are implicitly with external linkage. Ie. externis just redundant., just void initSfr(void); instead of extern void initSfr(); cppreference storage-class
The extern "C" { part makes no sense in your headers - there is nothing inside it. It's typicall to put extern "C" { on top of the header file to include everything inside. If your headers would be used by a C++ compiler, the functions names would be mangled and not properly resolved. I believe I would suggest to just remove the extern "C" { part.

Xcode 11 Objective C++ - Can't separate implementation from Header in ObjectiveC++ Project

I have created an Xcode standard Objective-C Project wanting to test integration with C++.
I have renamed my file accordingly to .mm etc.
I have created a C++ Class with a .hpp header and a .cpp imp file.
This is the header
class a {
private:
int anInt = 1;
public:
int getAnInt();
};
this is the imp
#include "PrismMatricies.hpp"
int a::getAnInt() {return anInt;}
in my ViewController.mm file I do this after importing the .hpp header
a ar;
NSLog(#"Some Log %i", ar.getAnInt());
Build Error Code in Xcode =
Undefined symbol: a::getAnInt()
If I move the function definition inside the header like this
class a {
private:
int anInt = 1;
public:
int getAnInt();
};
int a::getAnInt() {return anInt;}
The project works
Can anyone explain this to me as I simply don't get it
Note that "undefined symbol" is a link error, not a compile error, and your code certainly looks correct.
You will get that error if your .cpp isn't being linked into your build target. Make sure it's included in your build target's "compile sources" list. (You can also check that the target membership box is ticked in the File Inspector utility pane.)

How do I use functions from my file.c in Objective C

How can I use functions from my file.c in Objective C
I tried #include < file.c > in file2.m where I want to call this functions and got Lexical or Prepocesor Issue < file.c > not found and when I use #include "file" i got Apple Mach-O Linker (ID) Error. Same errors when I use #import instead of #include.
If in "file.m" you have a function like this:
void hello()
{
printf("Hello world!");
}
You also have to create a header file possibly called "file.h" in which you only declare the function but don't actually implement it;
void hello();
Then you have to #import or #include thw file.h file from file2.m.
Does your file.c have a file.h with the function declarations? You will want to #include that, and also make sure that file.c is compiled and linked in.

Singleton MFC extension DLL

I declare a singleton on a MFC extension DLL, like this:
//header file: SingleTon.h
class AFX_EXT_CLASS CMySingleton
{
public:
static CMySingleton* Instance()
{
if(!singleton)
singleton = new CMySingleton();
return singleton;
}
int a;
// Other non-static member functions
private:
CMySingleton() {}; // Private constructor
CMySingleton(const CMySingleton&); // Prevent copy-construction
CMySingleton& operator=(const CMySingleton&); // Prevent assignment
virtual ~CMySingleton() {};
static CMySingleton* singleton;
};
And in a cpp file I code the following line:
CMySingleton* CMySingleton::singleton = NULL;
Code 2:
CMySingleton *a;
a = CMySingleton::Instance();
The problem is when I code "code 2" in a Regular Dll, all works fine, but when I code "code 2" in another MFC extension DLL gives an error:
unresolved external symbol "private: static class CMySingleton* CMySingleton::singleton" (?singleton#CMySingleton##0PAV1#A)
I check correctly all the dependencies, via Project Dependencies.
Any idea?
The problem is in the AFX_EXT_CLASS macro.
#ifdef _AFXEXT
#define AFX_EXT_CLASS __declspec(dllexport)
#else
#define AFX_EXT_CLASS __declspec(dllimport)
#endif
Extension dll defines _AFXEXT and your class is exported, and main app (or a regular dll) doesn't define it so it's imported. But your second extension dll also defines _AFXEXT and your class declaration uses dllimport instead of dllexport and you get a linker error. The solution is to create your own macro for both dlls and use them instead of AFX_EXT_CLASS:
#ifdef EXTENSION_ONE
#define EXT_CLASS_ONE __declspec(dllexport)
#else
#define EXT_CLASS_ONE __declspec(dllimport)
#endif
Create EXTENSION_TWO and EXT_CLASS_TWO for your second dll. Define EXTENSION_ONE only in your first extension dll project, and EXTENSION_TWO only in your second extension dll project.

Objective-c++ symbol not found strangeness

hej.h
void hej();
hej.m
void hej(){}
main.mm
#import "hej.h"
int main(int argc, char *argv[])
{
}
This gives me:
"hej()", referenced from:
_main in main.o
symbol(s) not found
If I rename main.mm to main.m (single m), or hej.m to mm or cpp, then it works. (Though none of those "solutions" are preferable. Imagine you want to use a c-lib in a objc++ environment - you wouldn't wanna change the entire lib, maybe even couldn't, and you need to use it in objc++.)
What exactly is going on here?
When compiled in a C file (*.c, *.m), the declaration void hej() generates a linker reference to a C function named _hej. When compiled in a C++ file (*.cc, *.mm, etc.), the declaration generates a linker reference to a C++ 'mangled name', that includes in it a description of the arguments. (This is done to support function overloading, e.g. to differentiate void hej(int) from void hej(char*)). hej.m always creates the C name. When main.mm references the C++ name, it won't be found.
To resolve, ensure main.mm looks for a C name, not a C++ one. If you control hej.h, it's common to add something like the following, which would work when hej.h is included in either a C or a C++ file:
/* hej.h */
#ifdef __cplusplus
extern "C" {
#endif
void hej();
#ifdef __cplusplus
}
#endif
If you do not own hej.h, you could do the following in main.mm instead:
extern "C" {
#import "hej.h"
}
int main(int argc, char *argv[])
{
}