我有一个 C++ 函数(包装在 Xcode 中的 obj-c 文件中):
int64_t* findEdges(int64_t* pixels, int width, int height);
我想从 Swift 3 调用它并传入一个充满图片数据的缓冲区。在四处寻找之后,我调用它:
var ptr = (NSData(data: imageRep.tiffRepresentation!).bytes).bindMemory(to: Int64.self, capacity: 4 * height * width).pointee
let processor = findEdges(&ptr, width, height)
但是在访问 c++ 文件中的大约 30 或 40 个地址后,我遇到了 EXC_BAD_ACCESS
崩溃。
问题是我从 Swift 传递不安全的指针吗?正确的调用程序是什么?
最佳答案
这里至少是这种方法的一些问题。可能还有更多,因为我不知道 findEdges()
输入的确切含义以及该函数如何找到边缘。
NSData
的bytes
属性是未绑定(bind)到任何类型的原始指针。对bindMemory
的调用指示NSData
的内容将被视为 8 字节的4 * height * width
缓冲区整数,即32 * height * width
字节的缓冲区。我最近没有使用 TIFF 格式,但我强烈怀疑width x height
大小的图像的 TIFF 表示包含的字节数会比这少很多,所以即使缓冲区成功传递给findEdges
,试图将其视为比实际大得多会导致访问冲突。图像的 TIFF 表示的前 8 个字节被视为
Int64
并复制到ptr
变量,地址然后将其传递给findEdges
,后者将其视为4 * height * width
Int64
值的缓冲区的地址。但是,只有缓冲区中的第一个Int64
与图像有关(它包含其 TIFF 表示的前 8 个字节)。当findEdges
访问pixels
数组中的第二个Int64
时,它访问的内存与图像无关。访问更多(垃圾)Int64
值可能很幸运,但最终会尝试访问它无法访问的内容。
解决方案取决于 findEdges
所需的 pixels
是否包含与图像的 TIFF 表示完全相同的字节序列,或者是否需要一些转换。换句话说,我们可以说 TIFF 表示的前 8 个字节构成了 pixels
Int64
数组的第一个元素,第二个 8 字节 - 第二个元素等。
假设缓冲区可以按原样传递给 C++ 函数,这里是一个简短的简化示例,您可以根据需要进行调整。假设 C++ 函数接受一个 short
及其大小的数组,如下所示:
void processBuffer(int16_t * buf, int count) {
...
}
我们想从 Swift 中将 Data
的内容作为缓冲区传递。下面是一个人可能会这样做的方法:
var myData = ...
myData.withUnsafeMutableBytes({(p: UnsafeMutablePointer<Int16>) -> Void in
processBuffer(p, Int32(myData.count / 2))
})
请注意,缓冲区可以在 C++ 代码中修改,而不仅仅是读取,并且更改将反射(reflect)在 myData
中。
关于c++ - 将帧缓冲区从 Swift 传递到 C++ 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45822929/