我有一个使用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
上一步中创建的库: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文档,如果仍然没有官方支持,请询问Swift团队如何解决问题。
您应该遵循Swift所提供的有关C ABI约定中的函数导出的任何文档。盲目地执行它是令人怀疑的,如果行得通,这可能是偶然的,并且可能在将来的任何时候停止工作。
可悲的是,似乎至少在以下问题上并没有官方的支持:
为了使任何一种FFI都能非正式地工作,需要考虑以下几点:
弄清楚Swift遵循哪种调用约定,包括它是否使用隐藏参数或类似的东西。最好的情况是Swift在您的系统中使用通常的情况。
检查Swift导出的实际符号的名称是什么。也许他们被重伤了。
研究是否存在其他语言运行时自动执行的语义。例如,如果需要在代码之前/之后调用某些代码,或者可能需要初始化某些内容,等等。
在C ++方面,您应该在一个extern "C"
块中编写声明,以使该符号不会被C ++缠结:
extern "C" {
void StartWatcher();
}
也不必将其声明为函数指针。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句