我正在使用Swift的C API以及我需要调用的方法之一我需要提供一个
UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>
更多信息:
Swift界面:
public func presage_predict(prsg: presage_t, _ result: UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>) -> presage_error_code_t
原创C:
presage_error_code_t presage_predict(presage_t prsg, char*** result);
答案 0 :(得分:12)
通常,如果函数采用UnsafePointer<T>
参数
然后,您可以使用T
在“inout”参数中传递&
类型的变量。在您的情况下,T
是
UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
这是char **
的Swift映射。所以你可以调用C函数
如
var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil
if presage_predict(prsg, &prediction) == PRESAGE_OK { ... }
从Presage库I的文档和示例代码中
明白这会分配一个字符串数组并分配
此数组的地址为prediction
指向的变量。
为了避免内存泄漏,最终必须释放这些字符串
与
presage_free_string_array(prediction)
为了证明这确实有效,我采取了第一个 presage_c_demo.c部分演示代码并将其翻译过来 到斯威夫特:
// Duplicate the C strings to avoid premature deallocation:
let past = strdup("did you not sa")
let future = strdup("")
func get_past_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> {
return UnsafePointer(past)
}
func get_future_stream(arg: UnsafeMutablePointer<Void>) -> UnsafePointer<Int8> {
return UnsafePointer(future)
}
var prsg = presage_t()
presage_new(get_past_stream, nil, get_future_stream, nil, &prsg)
var prediction : UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = nil
if presage_predict(prsg, &prediction) == PRESAGE_OK {
for var i = 0; prediction[i] != nil; i++ {
// Convert C string to Swift `String`:
let pred = String.fromCString(prediction[i])!
print ("prediction[\(i)]: \(pred)")
}
presage_free_string_array(prediction)
}
free(past)
free(future)
这实际上起作用并产生了输出
prediction[0]: say prediction[1]: said prediction[2]: savages prediction[3]: saw prediction[4]: sat prediction[5]: same
答案 1 :(得分:3)
可能有更好的方法,但这会在游乐场中运行,并使用您想要的类型定义值r
:
func ptrFromAddress<T>(p:UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T>
{
return p
}
var myInt:Int8 = 0
var p = ptrFromAddress(&myInt)
var q = ptrFromAddress(&p)
var r = ptrFromAddress(&q)
定义ptrFromAddress
有什么意义,似乎什么都没做?我的想法是,Swift interop书中讨论可变指针的部分显示了许多通过将一些表达式作为参数传递来初始化它们的方法(如&x
),但似乎没有显示相应的方式来简单地调用{ {1}}的初始化程序。因此,让我们定义一个无操作函数,只是为了使用基于参数传递的特殊初始化方法
虽然我认为上述方法是正确的,但@alisoftware在另一个论坛中指出,这似乎是一种更安全,更惯用的方式来做同样的事情:
UnsafeMutablePointer
它更具惯用性,因为您使用的是Swift标准库提供的函数var myInt: Int8 = 0
withUnsafeMutablePointer(&myInt) { (var p) in
withUnsafeMutablePointer(&p) { (var pp) in
withUnsafeMutablePointer(&pp) { (var ppp) in
// Do stuff with ppp which is a UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>
}
}
}
,而不是定义自己的帮助器。它更安全,因为保证withUnsafeMutablePointer
仅在对闭包的调用范围内有效(只要闭包本身不存储指针)。