Вызов C # неуправляемого C ++, возвращающего строку символов squares
Вопрос
У меня есть некоторый код C #, вызывающий неуправляемую библиотеку DLL C ++.Метод, который я вызываю, предназначен для приема строки в качестве ссылки.Чтобы справиться с этим, я передаю StringBuilder , в противном случае возникает исключение StackOverflowException.
Это работает нормально, но при некоторых вызовах строка, возвращаемая из неуправляемого кода, представляет собой перепутанную строку, подобную этой:øŸE˜.,Ê.Я знаю, что это должно быть как-то связано с кодированием, но я попробовал несколько вещей, перечисленных ниже, и ничего не работает.Это не проблема в VB.Сетевой код, написанный кем-то другим для выполнения чего-то подобного.
Вот что я пробовал:1.Я использую это:[DllImport("dmphnx32.dll")], но безуспешно перепробовал все варианты кодировки.
- Пытался использовать кодировку.По умолчанию.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 ++.