2

アンマネージC++DLLを呼び出すC#コードがあります。私が呼び出しているメソッドは、文字列を参照として受け入れることを目的としています。これを処理するために、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

最初の 2 つの回答を試してみて、それらが役に立たないことを知った後、他の何かが疑わしいに違いないことがわかりました。アンマネージ コードの初期化パラメーターが実際に欠落しているアプリの別の場所に小さなバグを見つけました。これにより、奇妙にエンコードされた文字列が発生していました。

助けてくれてありがとう、コーリー

于 2009-10-30T13:21:31.257 に答える
0

StringBuilder の代わりに、IntPtr と Marshal クラスを使用してみてください。

SO、次のようになります。

[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... が機能するかを確認してください。ただし、ほとんどの C++ ライブラリでは ANSI が使用されているため、ANSI が機能するはずです。

于 2009-10-29T16:07:15.390 に答える