【问题标题】:Swift: How to call a C function loaded from a dylibSwift:如何调用从 dylib 加载的 C 函数
【发布时间】:2016-04-12 17:13:14
【问题描述】:

有没有办法从 Swift 调用从 dylib 加载的 C 函数?

这是我的 dylib 文件:

cppdemofile.cpp

#include "cppdemofile.h"

int add(int a, int b) {
    return a + b;
}

cppdemofile.h

#ifndef __CppDemoLibrary__cppdemofile__
#define __CppDemoLibrary__cppdemofile__

#pragma GCC visibility push(default)

extern "C" int add(int a, int b);

#pragma GCC visibility pop

#endif

编译到dylib并检查:

nm -gU libCppDemoLibrary.dylib
0000000000000f80 T _add

...复制libCppDemoLibrary.dylib~/lib...

Swift 程序

@IBAction func buttonClick(sender: NSButton) {
    let handle = dlopen("libCppDemoLibrary.dylib", RTLD_NOW)
    if (handle != nil) {
        var sym = dlsym(handle, "add")
        if (sym != nil) {
            let pointer = UnsafeMutablePointer<(CInt, CInt) -> CInt>(sym)

            // When debugging, I'm reaching up to this point...
            // but now, how do I call the 'add' function here???
            // var result = ???

            // label.stringValue = "Total: " + String(result)
        }
    }
}

如何调用add 函数?使用dylib可以吗?我应该将这些来源添加到我的 swift 项目中吗?

【问题讨论】:

标签: c swift macos dylib


【解决方案1】:

从 Swift 调用 add 函数是可能的,因为你 将其定义为与 extern "C" 具有 C 链接。

使库成为 Swift 模块(如上面 jtbandes 所建议的那样 cmets) 可能是更好的解决方案, 但这里是如何使用来自 Swift 的 dlsym() 返回的函数指针:

先添加

typedef int(*addFunc)(int, int);

到桥接头文件,或者定义

typealias addFunc = @convention(c) (CInt, CInt) -> CInt

在斯威夫特。然后以下工作:

let handle = dlopen(path, RTLD_NOW)
if (handle != nil) {
    var sym = dlsym(handle, "add")
    if (sym != nil) {
        let f = unsafeBitCast(sym, addFunc.self)
        let result = f(12, 45)
        print(result)
    }
    dlclose(handle)
}

当然,如果addFunc 与 加载函数的实际签名。


Swift 3 更新:

if let handle = dlopen(path, RTLD_NOW) {
    if let sym = dlsym(handle, "add") {
        let f = unsafeBitCast(sym, to: addFunc.self)
        let result = f(12, 45)
        print(result)
    }
    dlclose(handle)
}

【讨论】:

  • 这个效果很好。也感谢您提出将其作为一个模块的建议。
  • @Andres:不客气! – 然而,该建议来自 jtbandes 在他对您的问题的评论中:)
  • App Store 会拒绝使用此 API 的 iOS 应用吗?
  • @chrisamanse:如果你用它来调用非公共 API,很有可能。 (这个问题是关于 macOS,而不是 iOS。)
【解决方案2】:

为了在 Swift 中使用 C++ 代码,您需要将其包装在 C 函数或 Objective-C 类中。

另见Call a C++ function from Swift

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多