我正在为一些 sqlite3 函数构建一个小包装器。
sqlite3.dll 有一个函数 sqlite3_column_text16() 返回一个 UTF-16 字符串。这似乎是正确的调用函数,因为 PowerBasic 和 Windows(和 OLE)本机使用 UTF-16(称为 BSTR),但是,当我这样做时:
LOCAL pzValue AS ASCIIZ PTR
LOCAL ValLen AS LONG
LOCAL ColText AS STRING
pzValue = sqlite3_column_text16(ppStmt, 0) 'Returns column text ("Russ")
ValLen = sqlite3_column_bytes16(ppStmt, 0) 'Returns the byte length of column text (8)
ColText = &pzValue 'Assign a ASCIIZ PTR to a STRING - ISSUE HERE[/CODE]
ColText 仅包含 UTF-16 字符串的第一个字母。
这是有道理的(我认为),因为它是一个 UTF-16 字符串,所以第一个字节是有效的 ASCII,但第二个字节为零(空),所以在分配 ColText = &pzValue 时,ColText 被分配了所有文本直到第一个空字符。在本例中,字符串为“Russ”,因此 UTF-16 中的字节为“R0u0s0s0”(每个 ASCII 字符后跟一个空 (0)。
那么,如何将此 UTF-16 字符串转换为 PowerBasic STRING(即 BSTR)?
我检查了一些 sqlite3 包装器并找到了这段代码(SQLiteningServer.bas):
llColLength = sqlite3_column_bytes(rhSet, llDo)
if llColLength and llColLength <= 253 then
' It is not weird
lsaColumns(llDo) = mkbyt$(llColLength) & peek$(sqlite3_column_blob(rhSet, llDo), llColLength)
elseif llColLength = 0 then
' Its zero so check type for NULL
if sqlite3_column_type(rhSet, llDo) = 5 then
lsaColumns(llDo) = mkbyt$(254)
else
lsaColumns(llDo) = mkbyt$(0)
end if
else
' It is too long so add a Long
lsaColumns(llDo) = mkbyt$(255) & mkl$(llColLength) & peek$(sqlite3_column_blob(rhSet, llDo), llColLength)
end if
所以,在这段代码中,他们这样做:
lsaColumns(llDo) = mkbyt$(llColLength) & peek$(sqlite3_column_blob(rhSet, llDo), llColLength)
这几乎看起来他们正在内存中构建一个 BSTR,但不完全是。要成为有效的 BSTR,前导数值应该是表示字符串字节长度的 INT16,但在上面的代码中,它们使用前导 BYTE,所以它不是有效的 BSTR,对吧?我不知道。
如何获取 sqlite3_column_text16(ppStmt, 0) 返回的 UTF-16 字符串并将其转换为 PowerBasic STRING(这是标准 OLE BSTR)。