将 Swift 字符串数组转换为 const char * const *
Posted
技术标签:
【中文标题】将 Swift 字符串数组转换为 const char * const *【英文标题】:Array of Swift Strings into const char * const * 【发布时间】:2016-04-22 02:31:26 【问题描述】:我在将 Swift 字符串数组转换为带有签名的 c 函数数组时遇到问题:
PGconn *PQconnectStartParams(const char * const *keywords, const char * const *values, int expand_dbname)
在 Swift 中,const char * const * 显示为:
<UnsafePointer<UnsafePointer<Int8>>
所以我尝试转换名为“options”的字典 [String:String] 的内容,并将其提供给函数,如下所示:
var keys = [[Int8]]()
var values = [[Int8]]()
for (key, value) in options
var int8Array = key.cStringUsingEncoding(NSUTF8StringEncoding)!
keys.append(int8Array)
int8Array = value.cStringUsingEncoding(NSUTF8StringEncoding)!
values.append(int8Array)
pgConnection = PQconnectStartParams(UnsafePointer(keys), UnsafePointer(values), 0)
可以编译运行,但是函数不起作用。
任何见解将不胜感激。
【问题讨论】:
好的:你在谈论一个名为PQconnectdbParams()
的函数,但你正在调用一个名为PQconnectStartParams()
的函数...?
看看const char * const *keywords
。 keywords
是指向const
的指针,指向const char
的指针(与char const
相同,均表示“常量字符”)。这意味着您不是在寻找单个字符串(“空终止字符数组”),但您可能正在寻找字符串的 array。有点像char **argv
。我对 Swift 了解不多,但您必须弄清楚如何将 Swift 字符串转换为 C 空终止字符数组,然后必须找出如何将这些数组转换为 C 数组我认为是字符串。
对不起。笔误。正在查看文档的错误部分。修复了函数签名,你是对的,我不是在寻找一个以空值结尾的数组。我需要和 cstrings 数组。这就是我认为我在代码中生成的内容。
好的,看起来您正在尝试生成它。但是因为我对 Swift 一无所知,所以我只是想确保您尝试做正确的事情。
为什么.cStringUsingEncoding(NSUTF8StringEncoding)
会返回int8array
?我很困惑字符串和 int8
的关系如何?
【参考方案1】:
这并不完美,但至少它有效。
let options = ["key1": "value1", "key2": "value2", "key3": "value3", "key4": "value4"]
var keys = [String]()
for (key, value) in options
keys.append(key)
//you need to identify how many paramenters should be provided and set them following "static way"
//I did not find how to prepare this dynamically
let cKey1 = keys[0].cStringUsingEncoding(String.defaultCStringEncoding())!
let key1Pointer = UnsafePointer<CChar>(cKey1)
let cKey2 = keys[1].cStringUsingEncoding(String.defaultCStringEncoding())!
let key2Pointer = UnsafePointer<CChar>(cKey2)
let cKey3 = keys[2].cStringUsingEncoding(String.defaultCStringEncoding())!
let key3Pointer = UnsafePointer<CChar>(cKey3)
let cKey4 = keys[3].cStringUsingEncoding(String.defaultCStringEncoding())!
let key4Pointer = UnsafePointer<CChar>(cKey4)
let keysCArray = [key1Pointer, key2Pointer, key3Pointer, key4Pointer]
f(keysCArray)
/*
C - code
void f(const char * const *keywords)
printf("%s\n", keywords[0]);
printf("%s\n", keywords[1]);
printf("%s\n", keywords[2]);
printf("%s\n", keywords[3]);
*/
希望对您有所帮助。如果你愿意,我可以分享我的示例应用程序。
【讨论】:
谢谢梅利法罗。在发布问题之前,我已经尝试过这种方法,但不断收到 EXC_BAD_ACCESS。所以我认为这种方法是错误的。但是您关于确定有多少参数的观点使我意识到数组需要以空值终止。所以我向每个数组添加了一个 UnsafePointer这是 Swift3 中 Array 的一个扩展,它可以通用:
public extension Array
// Translate [String] to (const char * const *), which translates to Swift as
public func cStringArray() throws -> ArrayBridge<Element,CChar>
return try ArrayBridge<Element,CChar>(array:self)
guard let item = $0 as? String,
let translated = item.cString(using: .utf8) else
fatalError()
return translated
/*
We need to have this intermediate object around to hold on to the translated objects, otherwise they will go away.
The UnsafePointer won't hold on to the objects that it's pointing to.
*/
public struct ArrayBridge<SwiftType,CType>
let originals :[SwiftType]
let translated :[[CType]]
let pointers :[UnsafePointer<CType>?]
public let pointer :UnsafePointer<UnsafePointer<CType>?>
init(array :[SwiftType], transform: @noescape (SwiftType) throws -> [CType]) throws
self.originals = array
self.translated = try array.map(transform)
var pointers = [UnsafePointer<CType>?]()
for item in translated
pointers.append(UnsafePointer<CType>(item))
pointers.append(nil)
self.pointers = pointers
self.pointer = UnsafePointer(self.pointers)
然后你可以通过这样做得到正确的 C 兼容指针
try stringArray.cStringArray().pointer
【讨论】:
以上是关于将 Swift 字符串数组转换为 const char * const *的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中声明一个静态 const char 数组? [关闭]
error C2664: “int CWnd::GetWindowTextW(LPTSTR,int) const”: 不能将参数 1 从“char [10]”转换为“LP