0

我正在为一些 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)。

4

1 回答 1

1

ABSTR是指向后跟空字符的宽字符字符串的指针。文本前面的单词(在指针 -2 处)是字符串的长度。

查看SysAllocString(...)并了解从 UTF-16 文本SysAllocStringLen(...)创建的简单方法BSTR

于 2020-12-15T12:38:12.297 回答