2009-03-03 7 views
17

Wie kann ich einen char * von C dll passierenWie konvertiert man char * zu BSTR?

Hier Beispielcode VB:

void Cfunc(char *buffer,int len) 
{ 
    BSTR buf_bstr = SysAllocString((BSTR)buffer); 
    VBptr.VBfunc(buf_bstr,len); 
} 

Diese Funktion, In der tatsächlichen einigen anderen Werten nicht funktioniert eher auf die VB gesendet werden als die tatsächliche Wert.

Könnte jemand bitte eine Lösung vorschlagen?

+0

Können Sie ein Beispiel für eine ursprüngliche Zeichenfolge im Vergleich zum falschen Wert angeben, der gesendet wird? –

+0

Ihr (ursprüngliches) Problem scheint die Zeichenbreite zu sein. Ein BSTR ist immer ein breites Zeichen (COM ist alles Unicode). Ein Cast erweitert die Zeichen nicht automatisch, sondern interpretiert die Bytes als wchar_t *. – Richard

+0

Dieser Pseudocode weist ein Speicherleck auf. Sie rufen SysAllocString() auf, geben die Zuweisung jedoch nicht mehr frei, wenn Sie sie nicht mehr benötigen. – sharptooth

Antwort

2

Ich habe keine Einwände Antwort auf ajryan ist, aber hier ist eine Alternative ...

SysAllocString definiert ist, ein nehmen Parameter vom Typ OLECHAR *. Du gibst es Char *. Das sind nicht die gleichen Dinge. Es gibt bestimmte Umstände, wenn sie die gleiche Sache sein können, aber Sie können nicht davon abhängen. Zuallererst müssen Sie Ihren char * in einen OLECHAR * umwandeln. Es gibt ein Makro namens A2OLE, das dies für Sie tun kann, und in den Fällen, in denen char * und OLECHAR * identisch sind, kompiliert das Makro zu nichts (denke ich).

Weitere Informationen zu A2OLE und seinen Freunden finden Sie unter this page.

Oh, und das Umwandeln deines Char * in einen BSTR ändert das überhaupt nicht, es ist weder ein BSTR noch ein OLECHAR *.

+0

Btw, ein WCHAR * zu BSTR zu werfen ist auch eine schlechte Idee, wenn die Zeichenfolge nicht mit einer der SysAllocString() - Familienfunktionen zugeordnet wurde. Dies kann zu einem Absturz führen, wenn der Aufruf, den Sie an einen solchen Pseudo-BSTR übergeben, SysStringLen() aufruft. – sharptooth

21

Rufen Sie MultiByteToWideChar(), dann entweder SysAllocString() oder SysAllocStringLen() auf.

Vergessen Sie nicht, SysFreeString() aufzurufen, wenn Sie den BSTR nicht mehr benötigen.

Im Detail (SysAllocStringLen() Variante - es ist kürzer und schneller):

  1. Anruf MultiByteToWideChar() und übergeben Sie 0 als fünfte und sechste Parameter. Es gibt die Anzahl der Zeichen im Unicode-Äquivalent der ANSI-Zeichenfolge zurück. Denken Sie daran, dass ANSI-Zeichenfolgen beliebige Zeichen enthalten können, nicht nur ASCII, sodass Versuche, die Anzahl der Unicode-Zeichen bei Angabe der ANSI-Zeichenfolgenlänge manuell zu berechnen, in einigen Fällen funktionieren und in anderen nicht funktionieren.

  2. Weisen Sie einen Puffer für den BSTR mit SysAllocStringLen() zu. Übergeben Sie 0 als ersten Parameter und die Anzahl der Unicode-Zeichen als zweiten Parameter. Sie haben jetzt einen ordnungsgemäß zugewiesenen, jedoch nicht initialisierten BSTR. Es hat bereits Platz für die abschließende Null und diese nachgestellte Null ist richtig platziert.

  3. Rufen Sie MultiByteToWideChar() zum zweiten Mal auf und übergeben Sie den zugewiesenen BSTR dort. Die Funktion konvertiert die Zeichenfolge in Unicode und kopiert das Ergebnis in den BSTR. Jetzt haben Sie einen propelly zugewiesenen BSTR, der das Unicode-Äquivalent Ihrer ANSI-Zeichenfolge enthält.

  4. Führen Sie den BSTR in VB. Genießen.

  5. Rufen Sie SysFreeString() auf, um die BSTR freizugeben.

+0

Noch funktioniert mein Code nicht, ich habe das geändert. void Cfunc (char * Puffer, int len) { BSTR buf_bstr; ULONG cCharacters; if (0 == MultiByteToWideChar (0, 0, Puffer, cCharacter, buf_bstr, cCharacters)); VBptr.VBfunc (buf_bstr, len); } VB Exe ist abgestürzt. –

+0

Hallo Sharptooth .. ich bin neu zu diesem COM :( –

+1

Ich habe die Antwort bearbeitet, um eine Schritt-für-Schritt-Anleitung zu enthalten. – sharptooth

10

Dies ist der Code, den ich sharptooths Antwort mit schrieb, dass

int wslen = MultiByteToWideChar(CP_ACP, 0, str, strlen(str), 0, 0); 
    BSTR bstr = SysAllocStringLen(0, wslen); 
    MultiByteToWideChar(CP_ACP, 0, str, strlen(str), bstr, wslen); 
    // Use bstr here 
    SysFreeString(bstr); 

Anmerkung -1 für die Länge der Saite ergibt die Nullabschluss Verwendung in dem

1

Ergebnis enthalten ist Verwenden Sie anstelle von char * -Array _tchar * array.Bei Sysallocstring werden nur die Unicode-Zeichen in einer 32-Bit-Anwendung verwendet.