source

스위프트에서 C로 전화하려면 어떻게 해야 하나요?

goodcode 2022. 8. 19. 20:47
반응형

스위프트에서 C로 전화하려면 어떻게 해야 하나요?

스위프트에서 C 루틴을 호출할 수 있는 방법이 있나요?

iOS/Apple 라이브러리의 대부분은 C뿐이며, 아직 호출할 수 있습니다.

예를 들어 swift에서 objc 런타임 라이브러리를 호출할 수 있으면 좋겠습니다.

특히 iOS C 헤더를 브리지하려면 어떻게 해야 합니까?

네, 물론 Apple의 C 라이브러리와 상호 작용할 수 있습니다.방법은 다음과 같습니다.

기본적으로 C 타입, C 포인터 등은 Swift 오브젝트(예를 들어 C)로 변환됩니다.intSwift는CInt.

C와 Swift를 연결하는 방법에 대한 간단한 설명으로 사용할 수 있는 또 다른 질문을 위해 아주 작은 예를 만들었습니다.

main.discloss.main.discloss.

import Foundation

var output: CInt = 0
getInput(&output)

println(output)

UserInput.c

#include <stdio.h>

void getInput(int *output) {
    scanf("%i", output);
}

cliinput-Bridging-Header.h

void getInput(int *output);

정답은 여기 있습니다.

컴파일러는 Objective-C와 마찬가지로 C API를 Swift로 변환합니다.

import Cocoa

let frame = CGRect(x: 10, y: 10, width: 100, height: 100)

import Darwin

for _ in 1..10 {
    println(rand() % 100)
}

문서의 Objective-C API와의 상호작용을 참조하십시오.

만약 당신이 나만큼 XCode에 처음이고, Leandro의 답변에 올라온 단편들을 시험해 보고 싶다면:

  1. 파일 -> 신규 -> 프로젝트
  2. 프로젝트 프리셋으로 명령줄 도구를 선택하고 프로젝트 이름을 "cliinput"으로 지정합니다.
  3. 프로젝트 탐색기(왼쪽 파란색 패널)를 마우스 오른쪽 버튼으로 클릭하고 "새 파일..."
  4. 드롭다운 대화상자에서 파일 이름을 "UserInput"으로 지정합니다."헤더 파일도 작성" 상자의 선택을 취소합니다.[Next] (다음)을 클릭하면 XCode가 Bridging-Header.h 파일을 작성해야 하는지 여부를 묻습니다."예"를 선택합니다.
  5. 위의 Leandro 답변에서 코드를 복사하여 붙여넣습니다.재생 버튼을 클릭하면 xcode가 하단 패널에 내장된 터미널에서 컴파일 및 실행됩니다.단말기에 번호를 입력하면 번호가 반환됩니다.

게시물에서는 clang의 모듈 지원을 사용하여 이를 수행하는 방법에 대해서도 설명합니다.

CommonCrypto 프로젝트에서 이 작업을 수행하는 방법에 대한 프레임이지만 일반적으로 Swift 내에서 사용하고 싶은 다른 C 라이브러리에서 작동합니다.

zlib을 위해서 잠깐 실험을 해봤습니다.새로운 iOS 프레임워크 프로젝트를 만들고 다음과 같은 module.modulemap 파일을 포함하는 zlib 디렉토리를 만들었습니다.

module zlib [system] [extern_c] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
    export *
}

그런 다음 [Targets]-> [ Link Binary With Libraries ](라이브러리와 바이너리 연결)에서 추가 항목을 선택하고 libz.tbd를 추가합니다.

이 시점에서 빌드하는 것이 좋습니다.

그 후, 이하의 코드를 쓸 수 있었습니다.

import zlib

public class Zlib {
    public class func zlibCompileFlags() -> UInt {
        return zlib.zlibCompileFlags()
    }
}

zlib 라이브러리 이름을 앞에 둘 필요는 없습니다.단, 위의 경우 Swift 클래스 펑크를 C 함수와 동일하게 명명하고 조건 없이 Swift 펑크는 애플리케이션이 정지할 때까지 반복 호출됩니다.

c++ 의 경우는, 다음의 에러가 표시됩니다.

  "_getInput", referenced from: 

c++ 헤더 파일도 필요합니다.기능에 c-linkage를 추가한 후 브리지헤더에 헤더파일을 포함합니다.

스위프트 3

UserInput.h

#ifndef USERINPUT_H
#define USERINPUT_H    

#ifdef __cplusplus
extern "C"{
#endif

getInput(int *output);

#ifdef __cplusplus
}
#endif

UserInput.c

#include <stdio.h>

void getInput(int *output) {
    scanf("%i", output);
}    

main.discloss.main.discloss.

import Foundation
var output: CInt = 0
getInput(&output)
print(output)

cliinput-Bridging-Header.h

#include "UserInput.h"

여기 이것을 설명하는 원본 비디오입니다.

포인터를 다룰 때는 좀 다른 볼 왁스처럼 보입니다.까지 C POSIX C POSIX라고 read다음 중 하나:

enum FileReadableStreamError : Error {
case failedOnRead
}

// Some help from: http://stackoverflow.com/questions/38983277/how-to-get-bytes-out-of-an-unsafemutablerawpointer
// and https://gist.github.com/kirsteins/6d6e96380db677169831
override func readBytes(size:UInt32) throws -> [UInt8]? {
    guard let unsafeMutableRawPointer = malloc(Int(size)) else {
        return nil
    }

    let numberBytesRead = read(fd, unsafeMutableRawPointer, Int(size))

    if numberBytesRead < 0 {
        free(unsafeMutableRawPointer)
        throw FileReadableStreamError.failedOnRead
    }

    if numberBytesRead == 0 {
        free(unsafeMutableRawPointer)
        return nil
    }

    let unsafeBufferPointer = UnsafeBufferPointer(start: unsafeMutableRawPointer.assumingMemoryBound(to: UInt8.self), count: numberBytesRead)

    let results = Array<UInt8>(unsafeBufferPointer)
    free(unsafeMutableRawPointer)

    return results
}

언급URL : https://stackoverflow.com/questions/24004732/how-to-call-c-from-swift

반응형