c++ - 将帧缓冲区从 Swift 传递到 C++ 的正确方法是什么?

标签 c++ macos pointers swift3

我有一个 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() 输入的确切含义以及该函数如何找到边缘。

  1. NSDatabytes 属性是未绑定(bind)到任何类型的原始指针。对 bindMemory 的调用指示 NSData 的内容将被视为 8 字节的 4 * height * width 缓冲区整数,即 32 * height * width 字节的缓冲区。我最近没有使用 TIFF 格式,但我强烈怀疑 width x height 大小的图像的 TIFF 表示包含的字节数会比这少很多,所以即使缓冲区成功传递给 findEdges,试图将其视为比实际大得多会导致访问冲突。

  2. 图像的 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/

相关文章:

c++ - 最快的去偏移算法?

c++ - Qt - 拖动标题栏时防止窗口调整大小

c++ - 使用 GLEW、GLFW 和 g++ 编译在 OS X 10.10 下启用 OpenGL 4.1

c - 试图在 C 中返回指向二维数组的两个指针

c++ - 当客户端在虚拟机上运行时,getpeername() 返回我的本地主机地址

c++ - 决策和递归函数

swift - Cocoa SCNetworkInterface 获取媒体子类型

swift - 如何在 cocoa macos 中读取类的计算属性并获得通知?

c - 我练习的浮点异常(C语言)

c++ - 如何使用字符串的字符指针?