调用 ObjC++ 时未定义的符号来自 C++ 的方法

发布于 2025-01-11 09:06:03 字数 3977 浏览 3 评论 0原文

我在这里关注这个答案< /a> 使用 C++ 为 React Native 构建 TurboModule

但是,我需要使用仅在 AVFoundation 框架中可用的 Apple 库,该框架仅适用于 Obj-C 和 C++

因此,我认为我可以从常规 C++ 或至少很多互联网答案中调用 Obj-C++ 方法所见告诉我,我可以。

尽管如此,当我尝试编译 TurboModule 时,出现以下错误:

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)

我将其与以下文件放在一起的方式:

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;
}

并从我的 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++!"));
        }
      });
}

我认为这应该可行,但链接器抱怨符号对于我的体系结构未定义。我在互联网上浏览到这个错误是不明确的,与我的体系结构无关,更多地与我调用函数的方式有关,但我对 C++ 完全陌生,所以我不确定我是什么我做错了。

我在实现中调用 ObjC++ 方法的方式有什么问题?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

染墨丶若流云 2025-01-18 09:06:03

在我看来,您的 MyObject.mm 文件要么没有被编译,要么它的目标代码没有链接到您的最终二进制文件中。

  • 如果您使用的是 Xcode,请确保此源文件是您的目标的成员。 (它应该显示在目标的“构建阶段”的“编译源”部分中)
  • 如果使用其他构建系统,请确保使用正确的编译器构建 .mm 文件(以正确的模式进行 clang - 即 -ObjC++),并且生成的目标代码文件 (MyObject.o) 包含在链接步骤中。

It sounds to me as if your MyObject.mm file is either not being compiled, or its object code is not being linked into your final binary.

  • If you're using Xcode, make sure this source file is a member of your target. (It should show up in the "Compile Sources" section of your target's "Build Phases")
  • If using another build system, ensure that .mm files are built using the correct compiler (clang in the correct mode - i.e. -ObjC++) and that the resulting object code file (MyObject.o) is included in the link step.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文