При разработке приложения с помощью Flutter framework мне приходится использовать C++
и Objective-C
.
Иногда вам нужно вызвать функцию C++
из Objective-C
, а иногда вам нужно вызвать функцию Objective-C
из C++
.
Я просмотрел несколько статей, но не смог найти ответ, который искал.
Добавьте тестовый код. Это простой код.
обьц.м
@implementation Objc
-(int) objcSum:(int)num1 secondInt(int)num2{
return num1 + num2;
}
Cpp
int MyCpp::sum(int n1, int n2){
int result = objcSum(n1, n2);
return result;
}
Не могу дозвониться objcSum()
.
AppDelegate.m
MyCpp* mycpp = [[MyCpp alloc]init];
int res = mycpp->sum(10, 20);
NSLog("@res : %d", res);
Объект myCpp не создается, а заголовочный файл imported
, но на него вообще нельзя ссылаться.
Изменить
Вызов c++
от objc
прошел успешно.
Основываясь на вашем ответе, я написал код, как показано ниже.
Но вызов objc
из c++
выдает ошибку.
///ObjcSum.h
#ifndef objcSum_h
#define objcSum_h
#import <Foundation/Foundation.h>
@interface TDWObject : NSObject
-(NSInteger)addNum:(NSInteger)lhs second:(NSInteger)rhs;
@end
int TDWObjcSum(int num1, int num2);
#endif /* objcSum_h */
///ObjcSum.mm
#import "objcSum.h"
@implementation TDWObject
-(NSInteger)addNum:(NSInteger)lhs second:(NSInteger)rhs
{
return lhs + rhs;
}
@end
int TDWObjcSum(int num1, int num2)
{
return [[TDWObject new] addNum:num1 second:num2]; //Implicit conversion loses integer precision: 'NSInteger' (aka 'long') to 'int'
}
///Mycpp.h
class MySum {
public:
int ObjcCall(int num1, int num2);
};
///MyCpp.cpp
#include "mycpp.hpp"
#include "objcSum.h"
int MySum::ObjcCall(int num1, int num2)
{
int res = TDWObjcSum(num1, num2);
return res;
}
///AppDelegate.mm
MySum* mySum = new MySum();
int res = mySum->ObjcCall(10, 40);
delete mySum;
код ошибки
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:535:61: Unknown type name 'NSString'
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:539:30: Unknown type name 'NSString'
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:539:53: Format argument not an NSString
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:540:31: Unknown type name 'NSString'
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:540:63: Format argument not an NSString
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSZone.h:19:63: Unknown type name 'NSString'
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSZone.h:20:19: Unknown type name 'NSString'
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:523:1: Expected unqualified-id
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSZone.h:9:1: Expected unqualified-id
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObject.h:10:1: Expected unqualified-id
too many errors emitted, stopping now
Спасибо за Ваш ответ. Есть ли место, где я могу увидеть простой пример кода?
В то время как Objective-C
является строгим надмножеством C
, существует другой язык, называемый Objective-C++
, который является строгим надмножеством C++
. Вы можете использовать Objective-C++
для записи C++
и Objective-C
в одни и те же исходные файлы.
Другой вариант — избегать раскрытия каких-либо конкретных операторов C++
и Objective-C
и поддерживать их совместимость с подмножеством, доступным для обоих языков (то есть преимущественно для языка C
).
Это довольно просто, если вы скомпилируете свой проект с помощью Xcode и Apple Clang, просто переименуйте расширение исходного файла с m
на mm
(например, с objc.m
на objc.mm
). Это заставит компилятор принять код C++ в данном исходном файле. Например. если у вас есть заголовок C++
, определенный следующим образом:
// MyCpp.hpp file
#include <string>
struct MyCpp {
std::string var;
int sum(int a, int b);
};
Вы можете импортировать его в любой файл mm
, как и любой другой заголовок, и легко написать встроенный код C++:
// objc.mm
#import "MyCpp.hpp"
@implementation Objc
- (int)objcSum:(int)num1 secondInt(int)num2{
return MyCpp{}.sum(num1, num2);
}
Здесь все немного сложнее. C++ как язык программирования не определяет никакого интерфейса взаимодействия с Objective-C, поэтому лучшее, что вы можете сделать, это переключиться с единицы компиляции языка C++ на единицу компиляции языка Objective-C++, где оба синтаксиса приемлемы (обычно это просто означает переключение с расширения cpp
на расширение mm
). Опять же, если у вас есть интерфейс Objective-C, определенный следующим образом:
// MyObjc.h
#import <Foundation/Foundation.h>
@interface TDWObject: NSObject
- (NSInteger)addNum:(NSInteger)lhs toNum:(NSInteger)rhs;
@end
В некоторых классах C++ это можно вызвать без каких-либо проблем, при условии, что класс существует в модуле компиляции Objective-C++:
// MyCpp.mm
#import "MyCpp.hpp"
#import "MyObjc.h"
int MyCpp::sum(int a, int b) {
return [[TDWObject new] addNum:a toNum: b];
}
И Objective-C, и C++ поддерживают определенный синтаксис C, поэтому альтернативный подход к тому, чтобы оба языка вызывались друг из друга, состоит в том, чтобы ограничить заголовки только C-совместимыми операторами. Например. вы можете объявить заголовок таким образом для реализации C++:
// CppSum.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int TDWCppSum(int a, int b);
#ifdef __cplusplus
}
#endif
(Примечание: защита extern "C"
требуется, чтобы избежать искажения имен C++ при связывании этого заголовка с исходным кодом C++. В противном случае код C не сможет найти символы в скомпилированном объектном файле C++)
Однако файл реализации никак не ограничен, поэтому вы можете использовать любой код C++, поддерживаемый вашим компилятором:
// CppSum.cpp
#include "CppSum.h"
template<typename T>
class MySum {
public:
T sum(T lhs, T rhs) {
return lhs + rhs;
}
};
int TDWCppSum(int a, int b) {
return MySum<int>{}.sum(a, b);
}
В Objective-C это можно использовать так:
// objc.m
#import "CppSum.h"
@implementation Objc
- (int)objcSum:(int)num1 secondInt(int)num2{
return TDWCppSum(num1, num2);
}
Подход почти такой же: используйте только операторы C в заголовке и не раскрывайте там какую-либо реализацию Objective-C (например, операторы @interface
или @protocol
):
// ObjcSum.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int TDWObjcSum(int a, int b);
#ifdef __cplusplus
}
#endif
И опять же, вы можете использовать в реализации любые функции Objective-C:
// ObjcSum.m
#import "ObjcSum.h"
#import <Foundation/Foundation.h>
@interface TDWObject: NSObject
- (NSInteger)addNum:(NSInteger)lhs toNum:(NSInteger)rhs;
@end
@implementation TDWObject
- (NSInteger)addNum:(NSInteger)lhs toNum:(NSInteger)rhs {
return lhs + rhs;
}
@end
int TDWObjcSum(int a, int b) {
return [[TDWObject new] addNum:a toNum:b];
}
Для кода C++ это будет просто еще одна бесплатная функция:
// mycpp.cpp
#include "ObjcSum.h"
struct S {
void foo() {
auto result = TDWObjcSum(10, 15);
}
};
Произошла ошибка при вызове функции 'OBJC' из 'C++'. Отредактировал вопрос, добавив сообщение об ошибке. Есть что-то, что я упускаю??
@Jungwon, если вы используете C-подход, ваши заголовки не могут раскрывать какие-либо детали, относящиеся к Objective-C. т.е. он не должен содержать заголовков @interface
, @implementation
или Cocoa Touch framework. Код C++ ничего не знает о синтаксисе Objective-C, он может обрабатывать только функции C. В этом случае единственное, что разрешено в вашем файле ObjcSum.h
, — это сигнатура функции int TDWObjcSum(int num1, int num2);
. Все остальное нужно поместить в файл реализации, если вы хотите использовать заголовок в коде C или C++.
Ошибка устранена. Но я получаю другую ошибку. Showing Recent Messages Undefined symbol: TDWObjcSum(int, int)
@Jungwon, вам нужно обернуть объявление функции охранниками extern "C"
, чтобы C++ не искажал свое имя при импорте в модуль компиляции C++. Включил это в мой ответ
Вам нужно определить интерфейс C с обеих сторон или использовать Objective-C++.