繁体   English   中英

如何在 C++ 项目中使用 Swift static 库 (.a)?

[英]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库。
  • 其次,我构建了 C++ 项目,其中链接了在上一步中创建的libSwiftPackage.a库:
g++ -std=c++11 -L./SwiftPackage/.build/debug/ main.cc -lSwiftPackage -o swift_package

我究竟做错了什么? 我怀疑 Swift 库没有正确链接。

编辑

根据@Acorn 的回答,我做了两件事:

  1. extern "C"块中添加了我的StartWatcher声明
  2. 向我的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM