2

我有一些 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;
}

谢谢,科里

4

3 回答 3

1

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

于 2009-10-29T16:16:39.863 回答
0

您可以尝试使用 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++ 库使用的。

于 2009-10-29T16:07:15.390 回答
0

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

谢谢你的帮助,科里

于 2009-10-30T13:21:31.257 回答