Swift Package Manager로 빌드 한 순수한 Swift 패키지가 있습니다. 내 Package.Swift
모습은 다음과 같습니다.
// File: Package.swift
// swift-tools-version:5.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "SwiftPackage",
products: [
.library(
name: "SwiftPackage",
type: .static,
targets: ["SwiftPackage"]),
],
dependencies: [
],
targets: [
.target(
name: "SwiftPackage",
dependencies: []),
.testTarget(
name: "SwiftPackageTests",
dependencies: ["SwiftPackage"]),
]
)
이 Swift 코드에는 C ++ 코드에서 호출하려는 공용 함수가 포함되어 있습니다.
// File: SwiftPackage.swift
public func StartWatcher() {
// code ...
}
SwiftPackage.hh
다음 StartWatcher
과 같이 함수를 정의 하는 헤더 파일을 만들었습니다 .
// File: SwiftPackage.hh
void (*StartWatcher)();
이제를 main.cc
포함 SwiftPackage.hh
하고 StartWatcher
함수를 호출하는 파일 이 있습니다.
// File: main.cc
#include <SwiftPackage.hh>
int main() {
StartWatcher();
return 0;
}
그러나 빌드 된 실행 파일을 실행할 때 다음 오류가 발생합니다. ./swift_package' terminated by signal SIGSEGV (Address boundary error)
내 빌드 프로세스는 다음과 같습니다.
swift build --package-path SwiftPackage
. 이렇게하면 libSwiftPackage.a
라이브러리 가 생성 됩니다.libSwiftPackage.a
이전 단계에서 만든 라이브러리를 연결하는 C ++ 프로젝트를 빌드합니다 .g++ -std=c++11 -L./SwiftPackage/.build/debug/ main.cc -lSwiftPackage -o swift_package
내가 도대체 뭘 잘못하고있는 겁니까? Swift 라이브러리가 제대로 연결되지 않은 것 같습니다.
편집하다
@Acorn의 답변에 따라 두 가지 작업을 수행했습니다.
StartWatcher
선언을 추가 했습니다.extern "C"
@_cdecl("StartWatcher")
내 StartWatcher
Swift 함수에 이름이 라이브러리에서 엉망이되지 않도록 하는 속성 을 추가했습니다 .이제 다음과 같은 메시지가 다른 출력을 얻습니다.
Undefined symbols for architecture x86_64:
"static Foundation.Notification._unconditionallyBridgeFromObjectiveC(__C.NSNotification?) -> Foundation.Notification", referenced from:
@objc SwiftPackage.AppDelegate.applicationDidFinishLaunching(Foundation.Notification) -> () in libSwiftPackage.a(AppDelegate.swift.o)
@objc SwiftPackage.AppDelegate.applicationWillTerminate(Foundation.Notification) -> () in libSwiftPackage.a(AppDelegate.swift.o)
Swift 패키지에서 사용되는 다른 라이브러리에 액세스하는 데 어떤 종류의 문제가있는 것 같습니다.
요약 : 이것은 (아마도) 작동하도록 만들 수 있지만, 이것이 프로덕션 코드에서 사용되도록 의도 된 경우 유일한 올바른 접근 방식은 Swift 문서를 참조하는 것입니다. 아직 공식적인 지원이없는 경우에는 문의하십시오. 문제에 접근하는 방법
C ABI 규칙에서 함수를 내보내려면 Swift가 가지고있는 모든 문서를 따라야합니다. 맹목적으로 작동하는 것은 의심스럽고, 작동한다면 우연히 일을하게 될 것이며 미래의 어느 시점에서든 작동을 멈출 수 있습니다.
슬프게도 적어도 다음과 같은 질문에 따르면 그러한 것에 대한 공식적인 지원이없는 것 같습니다.
모든 종류의 FFI가 비공식적으로 작동하도록하려면 몇 가지 사항을 고려해야합니다.
숨겨진 매개 변수를 사용하는지 여부를 포함하여 Swift가 따르는 호출 규칙을 파악하십시오. 가장 좋은 시나리오는 Swift가 시스템에서 일반적인 시나리오를 사용하는 것입니다.
Swift에서 내 보낸 실제 기호의 이름이 무엇인지 확인하십시오. 아마도 그들은 망가 졌을 것입니다.
다른 언어 런타임이 자동으로 수행하는 의미가 있는지 조사하십시오. 예를 들어, 일부 코드를 전후에 호출해야하거나 초기화해야하는 경우 등이 있습니다.
C ++ 쪽에서 extern "C"
는 기호가 C ++로 얽혀 있지 않도록 블록에 선언을 작성해야합니다 .
extern "C" {
void StartWatcher();
}
함수 포인터로 선언 할 필요도 없습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다