Swift 如何转换NSArray<;NSInteger>;或NSData到UnsafeMutablePointer<;UInt8>;然后回到斯威夫特?

Swift 如何转换NSArray<;NSInteger>;或NSData到UnsafeMutablePointer<;UInt8>;然后回到斯威夫特?,swift,react-native,react-native-ios,Swift,React Native,React Native Ios,我想将NSArray或NSData转换为unsafemeutablepointer,以用于调用本机库。C中的本机方法公开为 typedef struct { int64_t len; uint8_t * _Nullable data; } ByteBuffer; int32_t pack(ByteBuffer request, ByteBuffer * _Nullable response, ExternError * _Nullable err); 这在斯威夫特变成了现实

我想将
NSArray
NSData
转换为
unsafemeutablepointer
,以用于调用本机库。C中的本机方法公开为

typedef struct {
    int64_t len;
    uint8_t * _Nullable data;
} ByteBuffer;

int32_t pack(ByteBuffer request, ByteBuffer * _Nullable response, ExternError * _Nullable err);
这在斯威夫特变成了现实

func pack(_ request: ByteBuffer, _ response: UnsafeMutablePointer<ByteBuffer>?, _ err: UnsafeMutablePointer<ExternError>?) -> Int32

// ByteBuffer
struct ByteBuffer {
    var len: Int64
    var data: UnsafeMutablePointer<UInt8>?
}
func包(uu请求:ByteBuffer,uu响应:UnsafeMutablePointer?,uu错误:UnsafeMutablePointer?)->Int32
//ByteBuffer
结构ByteBuffer{
变量len:Int64
var数据:非女性化指针?
}
此方法将从React Native调用,因此我对输入方法的swift定义为

func pack(request: Array<NSInteger>, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { }
func包(请求:数组,解析:RCTPromiseResolveBlock,拒绝:RCTPromiseRejectBlock)->Void{}
我没有取得多大进展,因为我很难理解swift如何使用指针

    func pack(request: Array<NSInteger>, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {

        var req = ByteBuffer(len: Int64(request.count), data: nil)
        req.data = UnsafeMutablePointer<UInt8>.allocate(capacity: request.count)
        
        let ptr = UnsafePointer<UInt8>([1, 2, 3])
        req.data?.assign(from: ptr, count: request.count)
        
        pack(req, _, _)
    }
func包(请求:数组,解析:RCTPromiseResolveBlock,拒绝:RCTPromiseRejectBlock)->Void{
var req=ByteBuffer(len:Int64(request.count),data:nil)
req.data=UnsafeMutablePointer.allocate(容量:request.count)
设ptr=UnsafePointer([1,2,3])
请求数据?分配(起始:ptr,计数:请求.计数)
包装(要求、包装、包装)
}
我不确定我是否在正确的轨道上,我将感谢任何方面的帮助。上面的代码还产生警告
初始化“UnsafePointer”会导致指针悬空


用目标C来写会更容易吗?

我设法通过了。在这里发布解决方案,以防其他人需要使用从Swift向C传递指针结构。技巧是使用
NSData的
withUnsafeBytes
键入或使用
OpaquePointer
创建
unsafemitablepointer
。这允许获取指向基础数据的指针,而无需进行复制。 只要调用相应的初始化的
NSData
,读回字节缓冲就很容易了

var请求=数组()
请求追加(16)
请求。追加(2)
让requestData=NSMutableData()
因为我在请求{
变量i=i
requestData.append(&i,长度:1)
}
让req=ByteBuffer(len:Int64(requestData.count),data:UnsafeMutablePointer(OpaquePointer(requestData.bytes)))
//如果使用NSData而不是NSMutableData,则可以使用以下代码
让req=ByteBuffer(len:Int64(requestData.count),
数据:requestData.withUnsafeBytes{UnsafeMutablePointer中的body(mutating:body)})
var res=ByteBuffer()
var err=ExternError()
让代码=didcomm\u生成\u密钥(req、res和err)
如果代码==0{
//使用NSData ctor可轻松获得响应
让responseData=NSData(bytesNoCopy:res.data!,长度:Int(res.len),freeWhenDone:true)
}

我认为你在通往Objective-C的道路上一脚踢开了。你必须在某个时候处理好它。我会考虑一下。注意,在最新的iPhone上,
NSInteger
有8个字节,而UInt8只有一个字节。因此,字节到字节的转换可能会产生意想不到的结果。@Cristik说得对。我的假设是,我必须在某个时候将其转换为NSData,因此这是一个很难避免的字节复制步骤。@Adrian我希望它能在Swift中优雅地完成,但也许不能。示例代码在这里,以防您需要更多上下文。如果您在团队中工作,我会将
request
重命名为
requests
。然后,我将执行
request{//do stuff}
,而不是
requests.forEach{request in//do stuff}
,因为其中一个依赖项(BoringSSL gRPC)无法在swift静态库中构建模块,我最终还是在Objective C中完成了这项工作。虽然Swift中的解决方案有效,但我最终还是不得不使用ObjC,因为我喜欢Swift,这一点也不令人失望。最终结果-我在日常工作中一直在转换遗留的Objective-C,我遇到了一些问题,比如迫使重新思考转换顺序等。恭喜你找到了答案。