So rufen Sie Swift 5.3-Code von Objective-C auf

Der erste Apple Silicon Mac mit dem M1-Chip ist endlich da. Es fühlt sich an, als würden die Vor- und Nachteile im Netz herumwirbeln.

Ich bin derzeit ein Mac-Benutzer, aber anstatt meinen Mac zu ersetzen, schaue ich mir seine mögliche Anwendung für das Satellitenprojekt an, an dem ich arbeite. Ich erwarte, dass die Bildverarbeitungsleistung pro Preis des neuen Mac extrem hoch ist und die Bildverarbeitungsleistung pro Stromverbrauch ebenfalls gut ist. Ich werde über das künstliche Satellitenprojekt in Elixir Adventskalender 2020 schreiben, also freuen Sie sich bitte darauf.

Anstatt iOS- und Mac-Apps zu entwickeln und den Mechanismus zum Aufrufen des C-Programms NIF von Elixir zu verwenden, rufen Sie die von Apple gesammelten Code-Assets von Swift wie Core Image und Core ML von Elixir auf. Ich habe diesen Artikel mit dem Ziel geschrieben, zu sehen, ob ich es schaffen könnte. Wenn Sie Swift von Objective-C aus aufrufen können, können Sie Objective-C von C aus aufrufen, sodass Sie Swift auch von Elixir aus aufrufen können.

In Bezug auf Swift gab es mit Ausnahme des Apple Developer Program nur Artikel mit alten Sprachspezifikationen. Daher ist dieser Artikel, der Swift 5.3 in Xcode 12.1 entspricht, dem neuesten Xcode ab 2020.11.12, ähnlich. Ich denke, der Artikel hat etwas Neues.

Ich benutze auch make in der Kommandozeile anstelle von Xcode, um Swift / Objective-C-Code zu kompilieren. Ich denke, die Art, Makefile zu schreiben, ist auch hilfreich.

Der fertige Code

Teilen Sie den Code sofort. Es wird auf GitHub mit Apache-2.0-Lizenz veröffentlicht.

https://github.com/zacky1972/swift_objc_test

Schneller Code (Angerufene)

Hier ist der Swift-Code, den ich aufrufen möchte:

ExampleClass.swift


import Foundation

@objc class ExampleClass: NSObject {
	var count = 0
	@objc func increment() {
		count += 1
		NSLog("increment")
	}
	@objc func increment(by amount: Int) {
		count += amount
	}
	@objc func reset() {
		count = 0
	}
}

Die Quelle dieses Codes ist hier. https://docs.swift.org/swift-book/LanguageGuide/Methods.html

Objective-C-Code (Anrufer)

Führen Sie die folgenden zwei Schritte aus, um von Objective-C aus anrufen zu können.

Der Code auf der Objective-C-Seite sieht folgendermaßen aus.

main.m


#import <Foundation/Foundation.h>
#import "ExampleClass-Swift.h"

int main(int argc, char** argv)
{
	ExampleClass *obj = [[ExampleClass alloc] init];
	[obj increment];
	NSLog(@"Testing");
}

Die Punkte sind wie folgt.

Alles was Sie tun müssen, ist es als Objective-C zu lesen und es normal aufzurufen.

Ausführungsergebnis

Das Ausführungsergebnis ist wie folgt.

% ./hello 
2020-11-12 18:47:57.204 hello[10554:225821] increment
2020-11-12 18:47:57.204 hello[10554:225821] Testing

Da die "Inkrement" -Methode früher aufgerufen wurde, heißt es erwartungsgemäß "Testen".

Das ist der ganze Code, den man vorbereiten muss.

Makefile

Werfen wir einen Blick auf das Makefile, um zu sehen, wie es erstellt wird.

Makefile


.phony: all clean

all: hello


main.o: main.m ExampleClass-Swift.h
	clang -c $< -o $@

ExampleClass.o: ExampleClass.swift ExampleClass-Swift.h
	swiftc -emit-object -parse-as-library $<

ExampleClass-Swift.h: ExampleClass.swift
	swiftc $< -emit-objc-header -emit-objc-header-path $@

hello: main.o ExampleClass.o
	swiftc $^ -o $@ -framework Foundation

clean:
	$(RM) hello *.o *.{swiftdoc,swiftmodule,swiftsourceinfo} ExampleClass ExampleClass-Swift.h

Die Punkte sind wie folgt.

Generierte Objective-C-Headerdatei

Die generierte Objective-C-Headerdatei lautet:

ExampleClass-Swift.h


// Generated by Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1)
#ifndef EXAMPLECLASS_SWIFT_H
#define EXAMPLECLASS_SWIFT_H
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"

#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif

#if __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif

#pragma clang diagnostic ignored "-Wauto-import"
#include <Foundation/Foundation.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if __has_include(<uchar.h>)
#  include <uchar.h>
# elif !defined(__cplusplus)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2  __attribute__((__ext_vector_type__(2)));
typedef float swift_float3  __attribute__((__ext_vector_type__(3)));
typedef float swift_float4  __attribute__((__ext_vector_type__(4)));
typedef double swift_double2  __attribute__((__ext_vector_type__(2)));
typedef double swift_double3  __attribute__((__ext_vector_type__(3)));
typedef double swift_double4  __attribute__((__ext_vector_type__(4)));
typedef int swift_int2  __attribute__((__ext_vector_type__(2)));
typedef int swift_int3  __attribute__((__ext_vector_type__(3)));
typedef int swift_int4  __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2  __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3  __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4  __attribute__((__ext_vector_type__(4)));
#endif

#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
#  define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
#  define SWIFT_CLASS_PROPERTY(...)
# endif
#endif

#if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#endif
#if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#endif
#if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#endif
#if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
#else
# define SWIFT_RELEASES_ARGUMENT
#endif
#if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define SWIFT_WARN_UNUSED_RESULT
#endif
#if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
#else
# define SWIFT_NORETURN
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
#  define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
#  define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_RESILIENT_CLASS)
# if __has_attribute(objc_class_stub)
#  define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
#  define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
# else
#  define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
#  define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif

#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif

#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif

#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
#  define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
#  define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
#  define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
#  define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# if __has_feature(generalized_swift_name)
#  define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# else
#  define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if !defined(SWIFT_UNAVAILABLE_MSG)
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
#endif
#if !defined(SWIFT_AVAILABILITY)
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
#endif
#if !defined(SWIFT_WEAK_IMPORT)
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#endif
#if !defined(SWIFT_DEPRECATED)
# define SWIFT_DEPRECATED __attribute__((deprecated))
#endif
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
#else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
#endif
#if !defined(IBSegueAction)
# define IBSegueAction
#endif
#if __has_feature(modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
@import ObjectiveC;
#endif

#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
#if __has_warning("-Wpragma-clang-attribute")
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wnullability"

#if __has_attribute(external_source_symbol)
# pragma push_macro("any")
# undef any
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="ExampleClass",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
# pragma pop_macro("any")
#endif


SWIFT_CLASS("_TtC12ExampleClass12ExampleClass")
@interface ExampleClass : NSObject
- (void)increment;
- (void)incrementBy:(NSInteger)amount;
- (void)reset;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop
#endif

Zusammenfassung

Dieser Befund ermöglicht es, Swift 5.3-Code von Objective-C aufzurufen. Durch Schreiben eines separaten Codes, der Objective-C von C aus aufruft, können Sie Swift von C aus aufrufen. Mit anderen Worten, Sie können Swift und Apples API von Elixir aus frei aufrufen. Banzai!

Vielen Dank

Dieses Forschungsergebnis wurde von A-STEP Tryout JPMJTM20H1 unterstützt, einem Unterstützungsprogramm für die optimale Entwicklung von Forschungsergebnissen im Projekt zur Entwicklung von Forschungsergebnissen der Japan Science and Technology Agency.

Recommended Posts

So rufen Sie Swift 5.3-Code von Objective-C auf
So rufen Sie AmazonSQSAsync auf
So implementieren Sie UICollectionView mit Code nur in Swift
Wie man guten Code schreibt
[Integrationstestcode] So wählen Sie ein Element aus date_select aus
So wenden Sie das C-Code-Format über die Befehlszeile an
Aufrufen von Klassen und Methoden
[Swift] So senden Sie eine Benachrichtigung
Wechseln Sie von Eclipse zu VS Code
So schreiben Sie leicht verständlichen Code [Zusammenfassung 3]
[Swift] So ersetzen Sie mehrere Zeichenfolgen
Rufen Sie C-Sprachfunktionen von Swift aus auf
So wechseln Sie von HTML zu Haml
So öffnen Sie eine Skriptdatei von Ubuntu mit VS-Code
[Swift5] So kommunizieren Sie von ViewController zu Model und übergeben einen Wert
[swift5] So legen Sie die Farbe hexadezimal fest
[Rails] Wie man von erb zu haml konvertiert
[Flattern] Wie verwende ich C / C ++ von Dart?
Java: So senden Sie Werte von Servlet zu Servlet
[Java] Fluss vom Quellcode zur Ausführung
[Swift5] So erstellen Sie einen Begrüßungsbildschirm
[Swift5] So implementieren Sie Animationen mit "lottie-ios"
So überschreiben Sie Firebase-Daten mit Swift
So zählen Sie UTF-8-Codepunkte schnell
Zurückgeben eines Werts vom Modell an den Controller mithilfe des [Swift5] -Protokolls
[Swift] Zusammenfassung zum Löschen von Elementen aus einem Array (persönliches Memo)
So rufen Sie benutzerdefinierte Dienste / Standarddienste über Liferay 7 / DXP-Workflow / Workflow-Skript auf
[swift5] So ändern Sie die Farbe der TabBar oder die Farbe des TabBar-Elements mit Code
Konvertiert vom String-Zeiger der C-Sprache zum Swift-String-Typ
So verknüpfen Sie Rails6 Vue (aus dem Umgebungsbau)
So erhalten Sie einen Heapdump aus einem Docker-Container
So sichern Sie von der Datenbank (DB) in die Seeds-Datei
Beachten Sie, wie Sie Swift Super Basic TableView verwenden
So erhalten Sie eine Klasse von Element in Java
Wie man Code schreibt, der objektorientiertes Ruby denkt
[Swift UI] So deaktivieren Sie ScrollsToTop von ScrollView
[Java] So wechseln Sie von Open JDK zu Oracle JDK