2009-03-03 17 views
17

¿Cómo puedo pasar un char * desde C DLL a VBCómo convertir char * a BSTR?

Aquí es código de ejemplo:

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

Esta función no está funcionando, en reales algunos otros valores son enviados a la VB en lugar de la actual valor.

¿Alguien podría sugerir una solución?

+0

¿Puedes dar un ejemplo de una cadena original frente al valor incorrecto que se envía? –

+0

Su problema (original) parece ser el ancho del carácter. Un BSTR siempre tiene caracteres anchos (COM es todo Unicode). Un elenco no ensanchará automáticamente los caracteres, pero interpretará los bytes como wchar_t *. – Richard

+0

Este pseudocódigo presenta una pérdida de memoria. Llama a SysAllocString(), pero no desasigne la cadena después de que ya no la necesite. – sharptooth

Respuesta

2

no tengo ninguna objeción a ajryan de respuesta, pero aquí es una alternativa ...

SysAllocString se define a tomar una parámetro del tipo OLECHAR *. Le estás dando un char * Estos no son la misma cosa. Existen ciertas circunstancias en las que podría ser ser lo mismo, pero no puede depender de ello. Entonces, antes que nada, necesitas convertir tu char * en un OLECHAR *. Existe una macro llamada A2OLE que puede hacer esto por usted, y en esos casos donde char * y OLECHAR * son lo mismo, la macro compila en cero (creo).

Consulte this page para obtener información sobre A2OLE y sus amigos.

Ah, y fundir su char * en un BSTR en realidad no lo cambia en absoluto, no es ni un BSTR ni un OLECHAR *.

+0

Por cierto, convertir un WCHAR * en BSTR es una mala idea si el string no ha sido asignado con una de las funciones de la familia SysAllocString(). Si lo hace, puede causar un bloqueo si la llamada que pasa tal pseudo-BSTR llama a SysStringLen() en él. – sharptooth

21

Llamar a MultiByteToWideChar(), luego a SysAllocString() o SysAllocStringLen().

No olvides llamar a SysFreeString() cuando ya no necesites el BSTR.

En detalle (SysAllocStringLen() variante - es más corto y más rápido):

  1. llamada MultiByteToWideChar() y pase 0 como parámetros quinto y sexto. Devolverá la cantidad de caracteres en el equivalente Unicode de la cadena ANSI. Recuerde, la cadena ANSI puede contener cualquier carácter, no solo ASCII, por lo que cualquier intento de calcular manualmente la cantidad de caracteres Unicode dada la longitud de la cadena ANSI puede funcionar en algunos casos y no funcionar en otros.

  2. Asigne un almacenamiento intermedio para el BSTR con SysAllocStringLen(). Pase 0 como el primer parámetro y la cantidad de caracteres Unicode como el segundo parámetro. Ahora tiene un BSTR correctamente asignado pero no inicializado. Ya tiene lugar para el cero final y este cero final está colocado correctamente.

  3. Llame a MultiByteToWideChar() por segunda vez y esta vez pase allí el BSTR asignado. La función convertirá la cadena en Unicode y copiará el resultado en el BSTR. Ahora tiene un BSTR asignado que contiene el equivalente de Unicode de su cadena ANSI.

  4. Pase el BSTR a VB. Disfrutar.

  5. Llame a SysFreeString() para desasignar el BSTR.

+0

Todavía mi código no funciona, lo he modificado así. void Cfunc (char * buffer, int len) { BSTR buf_bstr; ULONG cCharacters; if (0 == MultiByteToWideChar (0, 0, buffer, cCharacters, buf_bstr, cCharacters)); VBptr.VBfunc (buf_bstr, len); } VB Exe se ha estrellado. –

+0

Hola Sharptooth ... soy nuevo en este COM :( –

+1

He editado la respuesta para incluir un tutorial paso a paso – sharptooth

10

Este es el código que he escrito usando sharptooths respuesta

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); 

Tenga en cuenta que el uso de -1 para la longitud de los resultados de cadena en el terminador nulo que se incluye en el resultado

1

en lugar de char * array, pruebe _tchar * array. Porque Sysallocstring solo toma los caracteres Unicode en una aplicación de 32 bits.