macOS捆绑包之间的双向数据交换(快速) [英] Bidirectional data exchange between macOS Bundles (swift)

查看:64
本文介绍了macOS捆绑包之间的双向数据交换(快速)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在macOS捆绑包之间传递数据?

How can I pass data between macOS Bundles?

例如:MyApp.app将数据发送到MyBundle.bundle中的函数或类初始化程序,后者执行自己的逻辑在上面。甚至可以返回一个值,然后MyApp.app可以对其进行进一步处理。

eg: MyApp.app sends data to a function or class initialiser in MyBundle.bundle, which performs its own logic on it. It could even return a value, which MyApp.app can then process further.

例如,MyBundle中的一个函数(未嵌套在任何其他声明中):

Fo example, a function in MyBundle (not nested in any other declaration):

    void initialise(unsigned int frameCount) {…} // not a class initialiser btw

我已经尝试过:


  • 在MyBundle,然后使用 Foundation.Bundle 将其加载到MyApp中:

  • Declaring a class in MyBundle and then loading it in MyApp using Foundation.Bundle:

let class = (Bundle(url: url)!.classNamed("MyClass")! as! NSObject.Type).init()
// class is an instance of NSObject, but I can override the `init()` method 
// (in MyBundle) to do whatever. I have not found a way to implement an 
// initialiser with parameters, and it still be recognised here.


  • 在MyBundle中声明一个函数并使用 CFBundleGetFunctionPointerForName

  • Declaring a function in MyBundle and using CFBundleGetFunctionPointerForName to retrieve it.

    var bundles = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault, bundleDirectory, bundleExtension)! as Array
    var bundle1 = bundles.first! as! CFBundle
    
    var untypedFunctionPointer = CFBundleGetFunctionPointerForName(bundle, "initialise" as CFString)!
    
    let imp = unsafeBitCast(untypedFunctionPointer, to: IMP.self)
    
    let function = unsafeBitCast(imp, to: (@convention(c)(CUnsignedInt) -> Void).self)
    // If I specify parameters here, pass them in below, then try to use them in my objective c function, I get exc_bad_access.
    
    function(CUnsignedInt(1.0)) // Will work only when not trying to access parameters in the original objective c function.
    
    
    
    // Whatever @convention(c) function signature I use, the parameters are unusable in Objective C.
    


  • 两者的关键问题是我无法将数据作为参数传递。因此,打印语句将起作用,但不能使用参数。

    The critical issue with both is that I am unable to pass data in as parameters. So a print statement will work but no ability to use arguments.

    编辑:接受的答案显示了调用函数指针的正确方法。我谈论的崩溃是由于使用了无法正确桥接到C语言族的类型而导致的,因此在有疑问时请坚持使用Foundation库中的NSNumber,NSString等。

    Edit: Accepted answer shows the correct method for calling function pointers. The crashes I talked about are a result of using types which are not being bridged to the C family of languages properly, so stick to NSNumber, NSString etc. from the Foundation library when in doubt.

    推荐答案

    根据您的问题从Bundle中调用Swift函数和评论在 https://stackoverflow.com/a/56281093/5329717 中,我想您是在Swift中动态调用函数之后指针或带有 UnsafeBufferPointer 参数的Objective-C方法。

    Based on your question Call Swift function from Bundle and comments in https://stackoverflow.com/a/56281093/5329717 I presume you're after dynamically invoking in Swift a function pointer or an objective-c method with UnsafeBufferPointer argument.

    首先 UnsafeBufferPointer 将进行复制,以便进行互操作,我建议改用 OpaquePointer

    First of all UnsafeBufferPointer will make a copy so for interoping I recommend switching to OpaquePointer instead.

    假定函数指向带有签名 void cFunction(void * arg)的指针大小写:

    Assuming function to pointer case with signature void cFunction(void* arg):

    let fakeIMP = unsafeBitCast(functionToPointerAddress, to: IMP.self)
    unsafeBitCast(fakeIMP,to:(@convention(c)(OpaquePointer)->Void).self)(bufferArg)
    

    假定静态objective-c方法:

    Assuming static objective-c method:

    let receiverClass = NSClassFromString("SomeClass")
    let selector: Selector = NSSelectorFromString("selectorArg:")
    let methodIMP: IMP! = method_getImplementation(class_getClassMethod(receiverClass, selector))
    unsafeBitCast(methodIMP,to:(@convention(c)(AnyClass?,Selector,OpaquePointer)->Any).self)(receiverClass,selector, bufferArg)
    

    对于您提供的C签名

    void initialise(unsigned int frameCount);
    

    尝试一下:

    let imp = unsafeBitCast(functionToPointerAddress, to: IMP.self)
    unsafeBitCast(imp,to:(@convention(c)(Int)->Void).self)(1)
    

    这篇关于macOS捆绑包之间的双向数据交换(快速)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆