gpt4 book ai didi

c++ - 如何在 C++ 项目中使用 Swift 静态库 (.a)?

转载 作者:行者123 更新时间:2023-12-02 10:11:48 24 4
gpt4 key购买 nike

我有一个使用 Swift 包管理器构建的纯 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++ 代码中调用的公共(public)函数:
// 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) build
我的构建过程如下:
  • 首先,我通过运行 swift build --package-path SwiftPackage 构建 Swift 包。 .这将创建 libSwiftPackage.a图书馆。
  • 其次,我构建了链接 libSwiftPackage.a 的 C++ 项目。在上一步中创建的库:
  • g++ -std=c++11 -L./SwiftPackage/.build/debug/ main.cc -lSwiftPackage -o swift_package
    我究竟做错了什么?我怀疑 Swift 库没有正确链接。
    编辑
    根据@Acorn 的回答,我做了两件事:
  • 添加了我的StartWatcher extern "C" 中的声明 block
  • 添加属性 @_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 约定中的函数而提供的任何文档。盲目地这样做是值得怀疑的,如果这样做,它可能是偶然的,并且可能在 future 的任何时候停止工作。
    可悲的是,似乎没有官方支持这样的事情,至少根据以下问题:

  • Passing a Swift string to C
  • What is the best way to call into Swift from C?

  • 要使任何类型的 FFI 非正式地工作,需要考虑以下几点:
  • 弄清楚 Swift 遵循哪种调用约定,包括它是否使用隐藏参数或类似的东西。最好的情况是 Swift 在你的系统中使用常用的。
  • 检查 Swift 导出的实际符号的名称是什么。也许他们被破坏了。
  • 研究是否存在其他语言运行时自动执行的语义。例如,如果需要在之前/之后调用某些代码,或者可能需要初始化某些代码等。

  • 在 C++ 方面,您应该在 extern "C" 中编写声明。 block ,以便符号不会被 C++ 损坏:
    extern "C" {
    void StartWatcher();
    }
    也不需要将其声明为函数指针。

    关于c++ - 如何在 C++ 项目中使用 Swift 静态库 (.a)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63254013/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com