2009-10-29 5 views
2

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

Это прекрасно работает, но по некоторым вызовам строка, возвращающаяся из неуправляемого кода, представляет собой перемешанную строку, подобную этой: øŸ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

+2

Можете ли вы опубликовать объявление метода C++, который вы пытаетесь позвонить? – Christian

+1

И отправьте код C++, если он вам доступен (и достаточно небольшой для публикации). –

+0

Также отправьте фрагмент вызывающего кода – RobertL

ответ

0

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

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

0

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

SO, это будет выглядеть следующим образом:

[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++.

+0

Я пробовал этот метод и экспериментировал с различными типами кодирования, но я все еще возвращаю свою закодированную строку. Интересно, происходит ли что-то еще? –

+0

Вы заметили, что версия C++ использует «дескриптор» как HWND, и вы используете его как int? Насколько я знаю, HWND является Int64 (длинным). Единственное, что я могу придумать, это то, что, возможно, у вас проблема выравнивания. – Erich

1

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

+0

Это выглядело очень многообещающим его простотой, но, к сожалению, это не сработало. Я все равно получаю такое же странно закодированное значение. –