Как вызывать функции в С++ и Objective-C друг к другу

При разработке приложения с помощью 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

Вам нужно определить интерфейс C с обеих сторон или использовать Objective-C++.

molbdnilo 21.02.2023 07:29

Спасибо за Ваш ответ. Есть ли место, где я могу увидеть простой пример кода?

Jungwon 21.02.2023 07:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В то время как Objective-C является строгим надмножеством C, существует другой язык, называемый Objective-C++, который является строгим надмножеством C++. Вы можете использовать Objective-C++ для записи C++ и Objective-C в одни и те же исходные файлы.

Другой вариант — избегать раскрытия каких-либо конкретных операторов C++ и Objective-C и поддерживать их совместимость с подмножеством, доступным для обоих языков (то есть преимущественно для языка C).

Подход Objective-C++

Вызов кода C++ из Objective-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);
}

Вызов формы кода Objective-C++ C++

Здесь все немного сложнее. 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];
}

С подход

Вызов кода C++ из Objective-C

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

Вызов кода Objective-C из C++

Подход почти такой же: используйте только операторы 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 23.02.2023 01:50

@Jungwon, если вы используете C-подход, ваши заголовки не могут раскрывать какие-либо детали, относящиеся к Objective-C. т.е. он не должен содержать заголовков @interface, @implementation или Cocoa Touch framework. Код C++ ничего не знает о синтаксисе Objective-C, он может обрабатывать только функции C. В этом случае единственное, что разрешено в вашем файле ObjcSum.h, — это сигнатура функции int TDWObjcSum(int num1, int num2);. Все остальное нужно поместить в файл реализации, если вы хотите использовать заголовок в коде C или C++.

The Dreams Wind 23.02.2023 09:10

Ошибка устранена. Но я получаю другую ошибку. Showing Recent Messages Undefined symbol: TDWObjcSum(int, int)

Jungwon 23.02.2023 09:18

@Jungwon, вам нужно обернуть объявление функции охранниками extern "C", чтобы C++ не искажал свое имя при импорте в модуль компиляции C++. Включил это в мой ответ

The Dreams Wind 23.02.2023 09:49

Другие вопросы по теме