我有一些C#代码调用非托管C ++ DLL。我调用的方法是接受一个字符串作为ref。为了解决这个问题,我传入一个StringBuilder,否则会出现StackOverflowException。

这很好用,但在某些调用中,从非托管代码返回的字符串是一个混乱的字符串,如下所示:<!>#248; <!>#376; E <!>#732;。,< >!#202 ;.我知道这必须与编码有关,但我已经尝试了下面列出的几个东西,但没有任何作用。这不是VB.Net代码中的一个问题,其他人已经编写过类似的东西。

这是我尝试过的: 1.我正在使用它:[DllImport(<!> quot; dmphnx32.dll <!> quot;)],但是已经尝试了所有Charset选项而没有成功。

  1. 尝试使用Encoding.Default.GetBytes,Encoding.ASCII,Encoding.Unicode,其余部分没有成功。
  2. 我没有任何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 ++库使用的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top