I'm following this answer here to build a TurboModule for React Native using C++
However, I need to use an Apple library that is only available in the AVFoundation framework which only works for Obj-C and C++
Therefore, I thought I could call Obj-C++ methods from regular C++ or at least a lot of the internet answers I've seen tells me that I can.
Nonetheless, when I try to compile my TurboModule, I get the following error:
stderr: Undefined symbols for architecture x86_64:
"MyClassImpl::doSomethingWith(void*)", referenced from:
MyCPPClass::doSomethingWithMyClass() in libOneRecognizerTurboModuleApple--830559412.a(MyCPPClass.cpp.o)
"MyClassImpl::logMyMessage(char*)", referenced from:
MyCPPClass::doSomethingWithMyClass() in libOneRecognizerTurboModuleApple--830559412.a(MyCPPClass.cpp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The way that I'm putting this together is with the following files:
MyObject-C-Interface.h
#ifndef __MYOBJECT_C_INTERFACE_H__
#define __MYOBJECT_C_INTERFACE_H__
class MyClassImpl {
public:
MyClassImpl(void);
~MyClassImpl(void);
void init(void);
int doSomethingWith(void* aParameter);
void logMyMessage(char* aCStr);
private:
void* self;
};
#endif
MyObject.h
#import "MyObject-C-Interface.h"
@interface MyObject : NSObject {
int someVar;
}
- (int)doSomethingWith:(void*)aParameter;
- (void)logMyMessage:(char*)aCStr;
@end
MyObject.mm
#import "MyObject.h"
@implementation MyObject
MyClassImpl::MyClassImpl(void) : self(NULL) {}
MyClassImpl::~MyClassImpl(void) {
[(id)self dealloc];
}
void MyClassImpl::init(void) {
self = [[MyObject alloc] init];
}
int MyClassImpl::doSomethingWith(void* aParameter) {
return [(id)self doSomethingWith:aParameter];
}
void MyClassImpl::logMyMessage(char* aCStr) {
[(id)self doLogMessage:aCStr];
}
- (int)doSomethingWith:(void*)aParameter {
int result;
return result;
}
- (void)logMyMessage:(char*)aCStr {
NSLog(aCStr);
}
@end
MyCppClass.h
#ifndef __MYCPP_CLASS_H__
#define __MYCPP_CLASS_H__
class MyClassImpl;
class MyCPPClass {
enum { cANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42 };
public:
MyCPPClass(void);
~MyCPPClass(void);
void init(void);
int doSomethingWithMyClass(void);
private:
MyClassImpl* _impl;
int _myValue;
};
#endif
MyCppClass.cpp
#include "MyCPPClass.h"
#include "MyObject-C-Interface.h"
MyCPPClass::MyCPPClass(void) : _impl(NULL) {}
void MyCPPClass::init(void) {
_impl = new MyClassImpl();
}
MyCPPClass::~MyCPPClass(void) {
if (_impl) {
delete _impl;
_impl = NULL;
}
}
int MyCPPClass::doSomethingWithMyClass(void) {
int result = _impl->doSomethingWith(&_myValue);
if (result == cANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING) {
_impl->logMyMessage((char*)"Hello, Arthur!");
} else {
_impl->logMyMessage((char*)"Don't worry.");
}
return result;
}
And calling it this way from my TurboModule:
MyTurboModule.cpp
#include "MyCPPClass.h"
// rest of libraries
jsi::Value OneRecognizerTurboModule::getValueWithPromise(
jsi::Runtime& rt,
bool error) {
return createPromiseAsJSIValue(
rt, [error](jsi::Runtime& rt2, std::shared_ptr<Promise> promise) {
if (error) {
promise->reject("intentional promise rejection");
} else {
MyCPPClass* css;
css = new MyCPPClass();
css->doSomethingWithMyClass();
promise->resolve(jsi::String::createFromUtf8(rt2, "hello from c++!"));
}
});
}
I think that should work, but the linker is complaining that the symbols are undefined for my architecture. I browsed on the internet that this error is ambiguous and has nothing to do with my architecture and more to do with the way that I'm calling the function, but I'm completely new to C++ so I'm not sure what I'm doing wrong.
What's wrong with the way I'm calling the ObjC++ method in my implementation?