Domanda

Ho del codice C # che chiama in una DLL C ++ non gestita. Il metodo che sto chiamando intende accettare una stringa come riferimento. Per gestire questo passo in StringBuilder, altrimenti c'è StackOverflowException.

Funziona bene, ma su alcune chiamate la stringa che ritorna dal codice non gestito è una stringa confusa come questa: øŸE˜., Ê. So che questo deve avere qualcosa a che fare con la codifica, ma ho provato diverse cose, elencate di seguito, e nulla funziona. Questo non è un problema nel codice VB.Net che qualcun altro ha scritto per fare qualcosa di simile.

Ecco cosa ho provato: 1. Sto usando questo: [DllImport (" dmphnx32.dll ")], ma ho provato tutte le opzioni di Charset senza successo.

  1. Ho provato a usare Encoding.Default.GetBytes, Encoding.ASCII, Encoding.Unicode e il resto senza successo.

Non ho alcuna esperienza con C ++, quindi posso davvero usare l'aiuto.

Ecco il metodo 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);

Ecco il codice 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;
}

Ecco il codice C # che chiama il codice non gestito:

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

Grazie, Corey

È stato utile?

Soluzione 3

Dopo aver provato le prime 2 risposte e scoperto che non stavano aiutando, sapevo che qualcos'altro doveva essere sospetto. Ho trovato un piccolo bug da qualche altra parte nella mia app in cui in realtà mancava un parametro di inizializzazione sul codice non gestito. Ciò stava causando la mia stringa stranamente codificata.

Grazie per l'aiuto, Corey

Altri suggerimenti

Ok, vedo il tuo problema. Devi allocare una capacità per StringBuilder , non puoi semplicemente usare il valore predefinito.

Invece di StringBuilder, potresti provare a usare un IntPtr e la classe Marshal.

SO, sembrerebbe così:

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

Il codice chiamante sarebbe:

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

In questo modo puoi specificare la codifica corretta (cosa che non puoi fare con un generatore di stringhe, che presuppone che sia una codifica di tipo UTF). Sperimenta un po 'e vedi quali Marshal.PtrToString ... funzionano, anche se ANSI dovrebbe funzionare, poiché è quello che usano la maggior parte delle librerie C ++.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top