Pregunta

Tengo un código C # que llama a una DLL de C ++ no administrada. El método al que llamo está destinado a aceptar una cadena como referencia. Para manejar esto paso en un StringBuilder, de lo contrario hay una StackOverflowException.

Esto funciona bien, pero en algunas llamadas la cadena que regresa del código no administrado es una cadena desordenada como esta: & # 248; & # 376; E & # 732;., & # 202 ;. Sé que esto debe tener algo que ver con la codificación, pero he intentado varias cosas, enumeradas a continuación, y nada funciona. Esto no es un problema en el código VB.Net que alguien más ha escrito para hacer algo similar.

Esto es lo que he intentado: 1. Estoy usando esto: [DllImport (" dmphnx32.dll ")], pero he probado todas las opciones de Charset sin éxito.

  1. Intenté usar Encoding.Default.GetBytes, Encoding.ASCII, Encoding.Unicode y el resto sin éxito.

No tengo ninguna experiencia con C ++, así que realmente puedo usar la ayuda.

Aquí está el método DLLIMport:

[DllImport("dmphnx32.dll")]
        public static extern int PhxQueryDataAttributes(int handle,
                                        StringBuilder lTableName,
                                        StringBuilder lColumnName,
                                        ref short lIteration,
                                        ref short type,
                                        ref short maxLen,
                                        ref short endorsement,
                                        StringBuilder endorsementId);

Aquí está el código C ++:

short DMEXP PhxQueryDataAttributes(HWND handle,
                                   char *lTableName,
                                   char *lColumnName,
                                   short *lIteration,
                                   short *Type,
                                   short *MaxLen,
                                   short *Endorsement,
                                   char  *EndorsementID)
{

    handle = PhxInfo.HiddenHwnd;
    strcpy(lTableName, PhxInfo.TableName);
    strcpy(lColumnName, PhxInfo.ColumnName);


    *Type = PhxInfo.PhnxDataType;
    // max len
    *MaxLen = PhxInfo.MaxDataLen;
    *Endorsement = PhxInfo.Endorsement;
    strcpy(EndorsementID, PhxInfo.EndorsementID);
    // determine which table we need the iteration of
    *lIteration = PhxIterationArray[PhxInfo.sEffectiveTableID];

    return SUCCESS;
}

Aquí está el código C # que llama al código no administrado:

public int PhxQueryDataAttributes(int handle, ref string lTableName, ref string lColumnName, 
            ref short lIteration, ref short type, ref short maxLen, ref short endorsement, 
            ref string endorsementId)
        {
            var sbTableName = new StringBuilder();
            var sbColName = new StringBuilder();
            var sbEndId = new StringBuilder();

            var ret = RatingProxy.PhxQueryDataAttributes(handle, sbTableName, sbColName,
            ref lIteration, ref type, ref maxLen, ref endorsement, sbEndId);


            lTableName = sbTableName.ToString();
            lColumnName = sbColName.ToString();
            endorsementId = sbEndId.ToString();
return ret;
}

Gracias Corey

¿Fue útil?

Solución 3

Después de probar las 2 primeras respuestas y saber que no estaban ayudando, supe que otra cosa debía ser sospechosa. Encontré un pequeño error en otro lugar de mi aplicación donde realmente me faltaba un parámetro de inicialización en el código no administrado. Esto estaba causando mi cadena extrañamente codificada.

Gracias por la ayuda, Corey

Otros consejos

Ok, veo tu problema. Debe asignar una capacidad para el StringBuilder , no puede usar el predeterminado.

En lugar de StringBuilder, puede intentar usar IntPtr y la clase Marshal.

Entonces, se vería así:

[DllImport("dmphnx32.dll")]
    public static extern int PhxQueryDataAttributes(int handle,
                                    IntPtr lTableName,
                                    IntPtr  lColumnName,
                                    ref short lIteration,
                                    ref short type,
                                    ref short maxLen,
                                    ref short endorsement,
                                    IntPtr endorsementId);

El código de llamada sería:

public int PhxQueryDataAttributes(int handle, ref string lTableName, ref string lColumnName, 
        ref short lIteration, ref short type, ref short maxLen, ref short endorsement, 
        ref string endorsementId)
    {
        var sbTableName = Marshal.AllocHGlobal(1024);//Change these to the max length possible for each string.
        var sbColName = Marshal.AllocHGlobal(1024);
        var sbEndId = = Marshal.AllocHGlobal(1024);

        var ret = RatingProxy.PhxQueryDataAttributes(handle, sbTableName, sbColName,
        ref lIteration, ref type, ref maxLen, ref endorsement, sbEndId);


        lTableName = Marshal.PtrToStringAnsi(sbTableName);
        lColumnName = Marshal.PtrToStringAnsi(sbColName);
        endorsementId = Marshal.PtrToStringAnsi(sbEndId);
        return ret;
}

De esta manera puede especificar la codificación correcta (que no puede hacer con un generador de cadenas, que supone que es una codificación de tipo UTF). Experimente un poco y vea cuál de los Marshal.PtrToString ... funciona, aunque ANSI debería funcionar, ya que eso es lo que usan la mayoría de las bibliotecas de C ++.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top