C # вызов неуправляемого C ++, возвращающий строку символов квадратов - PullRequest
2 голосов
/ 29 октября 2009

У меня есть код C #, вызывающий неуправляемую C ++ DLL. Метод, который я вызываю, предназначен для приема строки в качестве ссылки. Для этого я передаю StringBuilder, иначе есть исключение StackOverflowException.

Это работает нормально, но при некоторых вызовах строка, возвращаемая из неуправляемого кода, представляет собой беспорядочную строку, например: øŸE˜., Ê. Я знаю, что это должно быть связано с кодированием, но я пробовал несколько вещей, перечисленных ниже, и ничего не работает. Это не проблема в коде VB.Net, который кто-то другой написал для чего-то подобного.

Вот что я пробовал: 1. Я использую это: [DllImport ("dmphnx32.dll")], но безуспешно перепробовал все варианты Charset.

  1. Пытался использовать Encoding.Default.GetBytes, Encoding.ASCII, Encoding.Unicode и остальные безуспешно.

У меня нет опыта работы с C ++, поэтому я действительно могу использовать помощь.

Вот метод 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);

Вот код 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;
}

Вот код C #, который вызывает неуправляемый код:

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

Спасибо, Corey

Ответы [ 3 ]

1 голос
/ 29 октября 2009

Хорошо, я вижу вашу проблему. Вам нужно выделить емкость для StringBuilder, вы не можете просто использовать значение по умолчанию.

0 голосов
/ 30 октября 2009

После того, как я попробовал первые 2 ответа и узнал, что они не помогают, я понял, что что-то еще должно быть подозрительным. В моем приложении я обнаружил небольшую ошибку, в которой фактически отсутствовал параметр инициализации неуправляемого кода. Это было причиной моей странно закодированной строки.

Спасибо за помощь, Corey

0 голосов
/ 29 октября 2009

Вместо StringBuilder вы можете попробовать использовать IntPtr и класс Marshal.

ТАК, это будет выглядеть так:

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

Телефонный код будет:

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

Таким образом, вы можете указать правильную кодировку (что нельзя сделать со строителем строк, который предполагает, что это кодировка типа UTF). Немного поэкспериментируйте и посмотрите, какие из Marshal.PtrToString ... работают, хотя ANSI должен работать, поскольку именно это используют большинство библиотек C ++.

...