代码之家  ›  专栏  ›  技术社区  ›  Corey Coogan

调用非托管C++返回方块符号串

  •  2
  • Corey Coogan  · 技术社区  · 16 年前

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

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

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

    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;
    }
    

    谢谢 科里

    3 回复  |  直到 16 年前
        1
  •  1
  •   leppie    16 年前

    好的,我明白你的问题了。您需要为服务器分配一个容量 StringBuilder ,不能只使用默认值。

        2
  •  0
  •   Erich    16 年前

    所以,它看起来是这样的:

    [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++库使用的。

        3
  •  0
  •   Corey Coogan    16 年前

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

    谢谢你的帮助, 科里