C#调用非托管C ++返回方块符号
题
我有一些C#代码调用非托管C ++ DLL。我调用的方法是接受一个字符串作为ref。为了解决这个问题,我传入一个StringBuilder,否则会出现StackOverflowException。
这很好用,但在某些调用中,从非托管代码返回的字符串是一个混乱的字符串,如下所示:<!>#248; <!>#376; E <!>#732;。,< >!#202 ;.我知道这必须与编码有关,但我已经尝试了下面列出的几个东西,但没有任何作用。这不是VB.Net代码中的一个问题,其他人已经编写过类似的东西。
这是我尝试过的: 1.我正在使用它:[DllImport(<!> quot; dmphnx32.dll <!> quot;)],但是已经尝试了所有Charset选项而没有成功。
- 尝试使用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;
}
谢谢, 科里
解决方案 3
在我尝试了前两个答案并得知他们没有帮助之后,我知道其他一些事情必须是可疑的。我在我的应用程序中的其他地方发现了一个小错误,其中我实际上错过了非托管代码的初始化参数。这导致了我奇怪编码的字符串。
感谢您的帮助, 科里
其他提示
好的,我看到了你的问题。您需要为StringBuilder
分配容量,不能使用默认值。
您可以尝试使用IntPtr和Marshal类来代替StringBuilder。
所以,它看起来像这样:
[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 ++库使用的。