如何在JavaScriptCore和Swift之间共享数组内存?

问题描述 投票:0回答:1

我正在尝试编写一个通过JavaScriptCore运行JS的Swift程序。我希望在程序的两个部分之间共享内存,以便JS写入Swift中创建的类型化数组缓冲区,然后Swift对其进行读写操作。这将是一种命令缓冲区。

例如,这是一些伪代码,大致代表我打算做的事情:

// js
let buf;
let i = 0;
setup() {
   buf = new Uint8Array(mem.alloc(N_BYTES));
}

frame() {
   i = 0;
   buf[i++] = some_command_enum;
}

// swift
func alloc(bytes : Int) -> the_memory {
    // allocate bytes uints and save the memory here
    // save a reference to the memory here
    // return the memory to use in JS
}

问题是,每当我尝试将实现实际添加到alloc时,JS都会通过异常报告该函数未定义,这意味着我的工作方式出现问题。不可返回的功能很好,所以我对此有所保留。

这是我的错误实现(请参阅注释):

// swift
@objc protocol JSMemoryExports: JSExport {
    static func alloc(_ byte_count: Int) -> JSObjectRef
    static func free(_ memory: JSObjectRef)
}

class JSMemory: NSObject, JSMemoryExports {
                                           // What is the correct return type?
    class func alloc(_ byte_count: Int) -> JSObjectRef {
        // temp
        let jsContext = JS_Controller.js.ctx!

        print("BYTE_COUNT", byte_count)

        // allocating a typed array
        let arr = JSObjectMakeTypedArray(jsContext.jsGlobalContextRef!, kJSTypedArrayTypeUint8Array, byte_count, nil)

        // just testing here to see how I'd write to this buffer (Note: is this the fastest way, or is all this memory binding slow?:
        // getting the raw bytes
        let ptr = JSObjectGetTypedArrayBytesPtr(jsContext.jsGlobalContextRef!, arr, nil)
        //let buf = JSObjectGetTypedArrayBuffer(jsContext.jsGlobalContextRef, arr, nil)
        let u8Ptr = ptr!.bindMemory(to: UInt8.self, capacity: byte_count)
        //u8Ptr[0] = 5
        return arr!
    }
}

...

jsContext["mem"] = JSMemory.self

// js
const buf = new Uint8Array(mem.alloc(8)) // JS Exception: TypeError: mem.alloc is not a function. (In 'mem.alloc(8)', 'mem.alloc' is undefined)

我已经看到了使用某些@convention属性的函数绑定变体。我是否打算改用它?

正确的做法是什么?

swift memory javascriptcore
1个回答
0
投票

除非您将来自不同来源的大量信息汇总在一起,否则文档不是很有帮助。看似可行的解决方案涉及使用在Swift中可调用的较旧C API的部分,不安全的指针,并确保绑定函数的返回值为JSValue?。这是有道理的,因为JavaScript函数都返回一个对象null undefined。可选类型反映了此行为。

这是我在进行中的代码,用于可能需要一些线索的任何人:

只是一个更新,我已经弄清楚了如何将旧的C API与新的受限于Swift的API混合使用。我尚未确定我没有泄漏内存,但是看来我已经找到了所需的东西。

如果您想知道:

@objc protocol JSMemoryExports: JSExport {
    // note that I'm returning an optional
    static func Uint8ArrayMake(_ count : JSValue) -> JSValue?
}

class JSMemory: NSObject, JSMemoryExports { 
    class func UInt8ArrayMake(_ count : JSValue) -> JSValue? {
        guard !count.isUndefined && !count.isNull else {
            return nil
        }

        let ref : JSValueRef = JSObjectMakeTypedArray(
            JS_Controller.js.ctx.jsGlobalContextRef!,
            kJSTypedArrayTypeUint8Array,
            Int(count.toInt32()),
            nil
        )!

        let ptr = JSObjectGetTypedArrayBytesPtr(
JS_Controller.js.ctx.jsGlobalContextRef!, ref, nil)
        return JSValue(jsValueRef: ref, in: JS_Controller.js.ctx)    
    }
}

以下是一些有用的参考资料://https://www.raywenderlich.com/7181017-unsafe-swift-using-pointers-and-interacting-with-chttps://medium.com/@shoheiyokoyama/manual-memory-management-in-swift-c31eb20ea8f

© www.soinside.com 2019 - 2024. All rights reserved.