Pergunta

Eu tenho algum código C # pôr em um C ++ não gerenciado DLL. O método que eu estou chamando é destinado a aceitar uma string como um ref. Para lidar com isso eu passar em um StringBuilder, caso contrário, há um StackOverflowException.

Isso está funcionando bem, mas em algumas chamadas a corda que vem de volta do código não gerenciado é uma seqüência confusa como esta:. ØŸE~, Ê. Eu sei que isso deve ter algo a ver com a codificação, mas eu tentei várias coisas, listados abaixo, e obras nada. Este não é um problema no código VB.Net que alguém tenha escrito para fazer algo semelhante.

Aqui está o que eu tentei: 1. Estou usando este:. [DllImport ( "dmphnx32.dll")], mas já tentou todas as opções Charset sem sucesso

  1. Tentou Encoding.Default.GetBytes uso, Encoding.ASCII, Encoding.Unicode, eo resto sem sucesso.

Eu não tenho nenhuma experiência com C ++ para que eu possa realmente usar a ajuda.

Aqui está o 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);

Aqui está o 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;
}

Aqui está o código C # que chama o código não gerenciado:

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

Obrigado, Corey

Foi útil?

Solução 3

Depois eu tentei as 2 primeiras respostas e aprendi que eles não estavam ajudando, eu sabia que algo mais deve ser suspeito. Eu encontrei uma pequena em algum lugar bug outra pessoa em meu aplicativo onde eu estava realmente faltando um parâmetro de inicialização do código não gerenciado. Isto estava causando a minha corda estranhamente codificado.

Obrigado pela ajuda, Corey

Outras dicas

Ok, eu vejo o seu problema. Você precisa alocar uma capacidade para o StringBuilder, você não pode apenas usar o padrão.

Em vez do StringBuilder, você pode tentar usar um IntPtr e da classe Marshal.

Assim, ficaria assim:

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

Chamando código seria:

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

Desta forma, você pode especificar a codificação correta (que você não pode fazer com um construtor de string, que assume que é um tipo UTF codificação). Experimentar um pouco, e ver qual dos Marshal.PtrToString ... mais trabalho, embora ANSI deve funcionar, que é o que a maioria das bibliotecas C ++ usar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top