C#调用非托管C++;返回正方形符号串 < >我有一些C++代码调用到非托管C++ DLL中。我调用的方法旨在接受字符串作为引用。要处理此问题,我将在StringBuilder中传递,否则会出现StackOverflowException

C#调用非托管C++;返回正方形符号串 < >我有一些C++代码调用到非托管C++ DLL中。我调用的方法旨在接受字符串作为引用。要处理此问题,我将在StringBuilder中传递,否则会出现StackOverflowException,c#,c++,encoding,unmanaged,dllimport,C#,C++,Encoding,Unmanaged,Dllimport,这可以正常工作,但在某些调用中,从非托管代码返回的字符串是一个混乱的字符串,如下所示:ŸE~,Ê。我知道这一定与编码有关,但我已经尝试了下面列出的几种方法,但没有任何效果。这在其他人编写的VB.Net代码中并不是一个问题 以下是我尝试过的: 1.我使用的是:[DllImport(“dmphnx32.dll”)],但尝试了所有字符集选项都没有成功 尝试使用Encoding.Default.GetBytes、Encoding.ASCII、Encoding.Unicode和其他内容,但未成功 我没有任

这可以正常工作,但在某些调用中,从非托管代码返回的字符串是一个混乱的字符串,如下所示:ŸE~,Ê。我知道这一定与编码有关,但我已经尝试了下面列出的几种方法,但没有任何效果。这在其他人编写的VB.Net代码中并不是一个问题

以下是我尝试过的: 1.我使用的是:[DllImport(“dmphnx32.dll”)],但尝试了所有字符集选项都没有成功

  • 尝试使用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

    您可以尝试使用IntPtr和封送处理类,而不是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++库使用的。

    OK,我看到了你的问题。您需要为StringBuilder分配一个容量,您不能只使用默认值。

    在我尝试了前两个答案并了解到它们没有帮助后,我知道肯定还有其他问题值得怀疑。我在我的应用程序中的其他地方发现了一个小错误,我在非托管代码中丢失了一个初始化参数。这导致了我奇怪的编码字符串

    谢谢你的帮助,
    Corey < /P>你能发布你试图调用的C++方法的声明吗?如果C++对你可用(而且小到可以发布),那么就发布它。我仍然得到相同的奇怪的编码值。我尝试了这种方法并尝试了不同类型的编码,但我仍然得到了我的编码字符串。我想知道还有什么事情发生吗?你注意到C++版本使用“句柄”作为HWND,你把它当作int使用吗?据我所知,HWND是一个Int64(长)。我唯一能想到的另一件事是,也许你有一个对齐问题。