Вызов C # неуправляемого C ++, возвращающего строку символов squares

StackOverflow https://stackoverflow.com/questions/1644325

Вопрос

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

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

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

  1. Пытался использовать кодировку.По умолчанию.getBytes, кодировка.ASCII, кодировка.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;
}

Спасибо, Кори

Это было полезно?

Решение 3

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

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

Другие советы

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

Вместо 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).Поэкспериментируйте немного, и увидите, кто из них Маршал.PtrToString...они работают, хотя ANSI должен работать, поскольку это то, что использует большинство библиотек C ++.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top