[英]How to use Swift static library (.a) in C++ project?
我有一个纯 Swift package,我用 Swift Z209802FB858E2C836205027DBBB5D9D 构建。 我的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 代码包含一个公共 function,我想从我的 C++ 代码中调用它:
// File: SwiftPackage.swift
public func StartWatcher() {
// code ...
}
我创建了一个 header 文件SwiftPackage.hh
我在其中定义了StartWatcher
function,如下所示:
// File: SwiftPackage.hh
void (*StartWatcher)();
现在我有我的main.cc
文件,其中包含SwiftPackage.hh
并调用StartWatcher
function:
// 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
库:g++ -std=c++11 -L./SwiftPackage/.build/debug/ main.cc -lSwiftPackage -o swift_package
我究竟做错了什么? 我怀疑 Swift 库没有正确链接。
编辑
根据@Acorn 的回答,我做了两件事:
extern "C"
块中添加了我的StartWatcher
声明StartWatcher
Swift function 添加了一个属性@_cdecl("StartWatcher")
,它应该确保该名称在库中没有被破坏。现在我得到一个不同的 output 这是一堆这样的消息:
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 package 中使用的其他库时存在某种问题?
总结:这可以工作(可能),但如果打算在生产代码中使用,那么唯一正确的方法是查阅 Swift 文档,如果仍然是这种情况没有官方支持,请询问Swift 团队如何解决这个问题。
您应该遵循 Swift 为导出 C ABI 约定中的函数而提供的任何文档。 盲目地这样做是值得怀疑的,如果这样做,它可能是偶然的,并且可能在未来的任何时候停止工作。
可悲的是,似乎没有官方支持这样的事情,至少根据以下问题:
要使任何类型的 FFI 非正式地工作,需要考虑以下几点:
弄清楚 Swift 遵循哪个调用约定,包括它是否使用隐藏参数或类似的东西。 最好的情况是 Swift 在您的系统中使用常用的。
检查 Swift 导出的实际符号的名称是什么。 也许他们被破坏了。
研究是否存在其他语言运行时自动执行的语义。 例如,如果需要在之前/之后调用某些代码,或者可能需要初始化某些代码等。
在 C++ 方面,您应该在extern "C"
块中编写声明,以便符号不会被 C++ 损坏:
extern "C" {
void StartWatcher();
}
也不需要将其声明为 function 指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.