Question

J'ai des appels de code C # dans une DLL C ++ non gérée. La méthode que j'appelle est destinée à accepter une chaîne en tant que réf. Pour gérer cela, je passe dans un StringBuilder, sinon il existe une exception StackOverflowException.

Cela fonctionne bien, mais sur certains appels, la chaîne renvoyée par le code non géré est une chaîne brouillée ressemblant à ceci: øŸE˜., Ê. Je sais que cela doit avoir quelque chose à voir avec l'encodage, mais j'ai essayé plusieurs choses, énumérées ci-dessous, et rien ne fonctionne. Ce n'est pas un problème dans le code VB.Net qu'une autre personne a écrit pour faire quelque chose de similaire.

Voici ce que j'ai essayé: 1. J'utilise ceci: [DllImport ("dmphnx32.dll")], mais j'ai essayé toutes les options de jeu de caractères sans succès.

  1. J'ai essayé d'utiliser Encoding.Default.GetBytes, Encoding.ASCII, Encoding.Unicode et le reste sans succès.

Je n'ai aucune expérience du C ++, donc je peux vraiment utiliser l'aide.

Voici la méthode 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);

Voici le code 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;
}

Voici le code C # qui appelle le code non géré:

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

Merci, Corey

Était-ce utile?

La solution 3

Après avoir essayé les 2 premières réponses et appris qu’elles n’aidaient pas, je savais que quelque chose d’autre devait être suspect. J'ai trouvé un petit bogue ailleurs dans mon application où il me manquait un paramètre d'initialisation sur le code non managé. Cela causait ma chaîne étrangement encodée.

Merci pour l'aide, Corey

Autres conseils

Ok, je vois ton problème. Vous devez allouer une capacité pour StringBuilder . Vous ne pouvez pas utiliser simplement la valeur par défaut.

Au lieu de StringBuilder, vous pouvez utiliser un IntPtr et la classe Marshal.

SO, cela ressemblerait à ceci:

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

Le code d'appel serait:

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 cette manière, vous pouvez spécifier le bon codage (ce que vous ne pouvez pas faire avec un constructeur de chaînes, ce qui suppose qu'il s'agit d'un codage de type UTF). Expérimentez un peu et voyez lequel des Marshal.PtrToString ... fonctionne, même si ANSI devrait fonctionner, car c’est ce que la plupart des bibliothèques C ++ utilisent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top