我需要调用采用2d数组的C函数。未来的数组是在Swift中创建的,通常为[String]
,但我对[[T]]
的情况也很感兴趣。
我正在调用的API指定了它的函数总是在必要时复制传递给它们的数据,所以我不想自己创建内容的副本只是为了传递它,而我只需要担心指针在我可以将它们传递给C函数之前一直有效。我目前的做法是
let addressArray = someArray.map { (array) in
array.withUnsafeBufferPointer({ (buffer) in
// get an array of addresses to each individual member
return buffer.baseAddress
})
}
addressArray.withUnsafeBufferPointer { bufferPointer in
someCFunction(bufferPointer.baseAddress)
// do something with someArray to attempt to ensure that the pointers are valid past the lifetime of the withUnsafeBufferPointer call
}
这是可行的,但是由于据说从withUnsafeBufferPointer
返回的指针仅在该范围内有效,所以这显然是错误的(尽管可以肯定,始终要求someArray
保持活动直到我用someCFunction
完成后,我非常有信心它不会在短期内中断)。但是必须有更好的方法。它是什么?
答案 0 :(得分:0)
根据您的经验,您的代码似乎偶尔会起作用。但是正如您所写的那样,您的代码是错误的,因为withUnsafeBufferPointer
返回的指针仅在其闭包参数范围内有效。
我不明白您的意思短期内不会破坏,但我建议您不要对未记录和不清楚的行为充满信心。
您可能需要创建一些稳定的指针,可以通过显式分配区域来实现。
当我需要UnsafePointer<UnsafePointer<T>>
来传递嵌套数组[[T]]
的内容时,我会写这样的东西。 (假设T
是原始类型。)
let bufPtrArray = someArray.map {subArray -> UnsafeMutableBufferPointer<T> in
let bufPtr = UnsafeMutableBufferPointer<T>.allocate(capacity: subArray.count)
_ = bufPtr.initialize(from: subArray)
return bufPtr
}
defer {bufPtrArray.forEach{bufPtr in bufPtr.deallocate()}}
let addressArray = bufPtrArray.map {bufPtr in UnsafePointer(bufPtr.baseAddress!)}
addressArray.withUnsafeBufferPointer { bufferPointer in
someCFunction(bufferPointer.baseAddress!)
//...
}
或者,如果您不需要在//...
中指定的代码,则只需编写:
someCFunction(addressArray)
答案 1 :(得分:-1)
对我来说问题是问题的所有前提似乎都是错误的。 Swift不会复制任何不必要的内容,因此传递实际值不一定没有任何效率。您可以可以传递一个需要C数组的Swift数组。而且,实际上并没有多维C数组之类的东西,因此您可以传递一个一维数组(当然,可以适当安排)。
例如,这是一种方法,该方法采用int
数组以及有关“行”(r
)和“列”(c
)的大小的信息是(来自https://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/的代码):
- (void) giveMeACArray: (int*) array r: (int) r c: (int) c {
int i, j, count;
int *arr[r];
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count;
// let's test it
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", arr[i][j]);
}
让我们说这是一个名为Thing的Objective-C类的实现的一部分。好的,现在我们在Swift中:
let t = Thing()
var arr : [CInt] = [1,2,3,4,5,6,7,8,9,10,11,12]
t.giveMeACArray(&arr, r: 3, c: 4)
没有复制任何内容,并且打印了正确的答案。所以我看不到您的缓冲区指针是什么。