简体   繁体   中英

Create BSTR from ASCIIZ PTR in PowerBasic sqlite3 Wrapper

I'm building a small wrapper for some sqlite3 functions.

sqlite3.dll has a function sqlite3_column_text16() that returns a UTF-16 string. This seems like the right function to call since PowerBasic and Windows (and OLE) use UTF-16 natively (called a BSTR), however, when I do this:

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 only contains the first letter of the UTF-16 string.

This makes sense (I think) because it's a UTF-16 string, so the first byte is valid ASCII, but the second byte is zero (null), so in the assignment ColText = &pzValue, ColText is assigned all the text up to the first null character. In this case, the string is "Russ", so the bytes in the UTF-16 are "R0u0s0s0" (each ASCII character is followed by a null (0).

So, how do I convert this UTF-16 string to a PowerBasic STRING (which is a BSTR)?

I checked some sqlite3 wrappers and found this code (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

So, in this code they are doing this:

lsaColumns(llDo) = mkbyt$(llColLength) & peek$(sqlite3_column_blob(rhSet, llDo), llColLength)

Which almost looks like they are constructing a BSTR in memory, but not exactly. To be a valid BSTR, the leading numeric value should be an INT16 indicating the byte length of the string, but in the code above, they are using a leading BYTE, so it's not a valid BSTR, right? I don't know.

How do I take a UTF-16 string returned by sqlite3_column_text16(ppStmt, 0) and convert it to a PowerBasic STRING (which is a standard OLE BSTR).

A BSTR is a pointer to a string of wide characters followed by a null character. The word preceding the text (at pointer -2) is the length of the string.

Look at SysAllocString(...) and SysAllocStringLen(...) for simple methods of creating a BSTR from your UTF-16 text

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM