Newsgroup: it.comp.lang.c++
Titolo: [?] Byte, Stringhe, BSTR - VB e dll

Salve,
il mio problema è il seguente:
nelle versioni precedenti di Visual Basic era possibile utilizzare quasi
indifferentemente le stringhe e le matrici di byte. Nella versione 5 questo
non è più possibile in quanto viene utilizzato il formato UNICODE al suo
interno e il formato ANSI per comunicare con l'esterno.
Il mio problema è dunque quello di convertire l'array di byte in una
stringa.
Per fare questo ho pensato di ricorrere ad una dll, passandogli l'indirizzo
del primo byte dell'array, il numero di caratteri che volevo copiare e la
stringa da riempiere.
Ho quindi scritto
#include <windows.h>
#include <ole2.h>
extern "C"
BOOL _stdcall ConvertiByte(char *pByte, short lenByte, BSTR originalString)
{
BOOL esito;
esito = SysReAllocStringLen(&originalString, (BSTR)pByte, lenByte);
return esito;
}
Detta procedura funzione (almeno sembra) a condizione che nel progetto di VB
alla stringa sia assegnata una lunghezza definita. Inoltre il numero di
caratteri copiati non è quello definito da lenByte ma il doppio.
es:
supponiamo di avere una matrice di caratteri b contenente i seguneti
caratteri "Tanto va la"
se in VB scrivo
ConvertiByte b(0), 2, MyStringa (con MyStringa as string*10)
dopo la chiamata MyStringa = "Tant      "
Domanda: qualcuno sa spiegarmi che cosa ho effettivamente scritto?
Dall'help pensavo che SysReAlloccStringLen mi riallocasse anche la lunghezza
della stringa, così da non dovere allocarla preventivamente, e soprattutto
perchè mi raddoppia i caratteri.
Ringrazio in anticipo
Bruno La Torre

interno e il formato ANSI per comunicare con l'esterno.
Il problema principale, penso, e' in questa affermazione, che non
e' corretta; cioe`, non e' vero che VB usa "il formato ANSI per
comunicare con l'esterno" -- spesso e volentieri, usa invece
Unicode (in particolare, tutte le "stringhe di caratteri" che vengono
scambiate fra moduli via COM/OLE/Automation/ecc sono in
Unicode).  Piu` in particolare, SysReallocStringLen prende come
secondo argomento un "OLECHAR FAR*" -- e OLECHAR, in
Windows a 32 bit, e' wchar_t (carattere di 16 bit; Unicode).  Tu
invece le passi un puntatore a caratteri ANSI, ma lei non lo sa
(hai fatto un cast del tuo char* a BSTR, che in questo contesto
equivale a OLECHAR* cioe` a wchar_t*) -- non fa nessun tipo
di conversione, e copia solo il numero di "caratteri" che tu hai
chiesto, a due byte per carattere (per cui, avendo tu invece dei
caratteri di solo 1 byte l'uno, osservi il "raddoppio" che hai visto).
Puoi invece operare cosi`:
    -- nella SysReallocStringLen, passa come secondo
        argomento ("stringa-sorgente") il valore 0 (o NULL,
        se preferisci, tanto e` eguale);
    -- poi, chiama una funzione di conversione ANSI->UNICODE
        per riempire lo spazio allocato al punto precedente con
        il valore Unicode corrispondente all'ANSI che hai in
        ingresso -- ad esempio, mbstowcs puo` fare al caso tuo
        (non preoccuparti del fatto che il character set di input
        sia detto "multibyte" -- se hai in input solo stringhe ANSI,
        quel "multi" si riduce a 1 carattere/byte senza problemi,
        in pratica).
Alcuni dei sintomi che mi riporti mi lasciano perplesso (non
so, ad esempio, perche` il tuo codice funzioni solo se la BSTR
e' dichiarata con lunghezza fissa -- non dovrebbe essere cosi`!),
ma suggerisco di vedere se questo tipo di approccio funziona
meglio -- se poi da` ancora problemi, possiamo cercare di
farne il debug.
Alex


Grazie per la risposta. Per il momento, proseguendo negli esperimenti, ho
modificato la dll nel seguente modo
#include <windows.h>
#include <string.h>
#include <ole2.h>
extern "C"
BSTR _stdcall ConvertiByte(char *pByte, short lenByte)
{
 BSTR stringa;
 stringa = SysAllocStringByteLen(NULL,lenByte);
 strncpy((char*)stringa, pByte,lenByte);
 return stringa;
}
e in VB
Declare Function ConvertiByte in "MyConv" (b as byte, byval nCar as integer)
as string
Studierò comunque le tue osservazioni, e farò sapere
Grazie ancora
Bruno La Torre