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

Xoroxoxoxoxoxoso

我有一个使用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软件包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. StartWatcher在一个代码extern "C"块中添加了我的声明
  2. @_cdecl("StartWatcher")在我的StartWatcherSwift函数中添加了一个属性该属性应确保该名称在库中没有损坏。

现在我得到一个不同的输出,它是一堆这样的消息:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Android库项目中使用匕首

如何在Java项目中使用Kotlin库?

如何在Swift项目中使用Objective-C CocoaPods

如何使用CMake在项目中添加预构建的静态库?

如何在Elixir项目中使用开源Erlang库?

如何在Swift项目中使用ECSlidingViewController

如何在Swift项目中使用TPKeyboardAvoiding?

如何在Swift 3中使用我的静态库(.a)

如何在我的Swift项目中使用Objective-C项目

如何在Swift项目中使用目标C框架类?

如何在Swift项目中使用Superpowered lib

如何在目标c-swift桥接项目中使用intentdefinition文件?

C项目中的C ++静态库链接

如何在Django项目中使用静态文件?

如何在项目中使用Angular库中的服务

如何在AOSP项目中使用预建的c ++静态/共享库

如何在Scalajs项目中使用Javascript库

我如何在C#项目中使用LightStreamer DotNetStandard库

如何在C ++项目中使用共享动态库?

如何在Maven项目中使用ASM库

将iOS Cocoa静态库项目中的Objective-C代码与iOS应用程序项目中的Swift代码一起使用

如何在橡皮筋项目中使用Makefile.ios创建静态库

如何在Android主项目中包含库项目中使用的AAR文件

如何在Swift tvOS项目中使用TVML文档?

如何在swift3项目中使用目标c视图控制器

如何通过迦太基在Obj-C项目中使用Swift库

如何在 iOS 项目中构建和使用 C 库?

如何在我的整个项目中使用 phpdotenv 库?

如何在 VS 2019 或 CLion 项目中使用“webrtc.lib”静态库?