スクエアシンボルの文字列を返すアンマネージC ++のC#呼び出し
質問
アンマネージC ++ DLLを呼び出すC#コードがあります。私が呼び出しているメソッドは、文字列を参照として受け入れることを目的としています。これを処理するには、StringBuilderを渡します。それ以外の場合は、StackOverflowExceptionがあります。
これは正常に機能していますが、一部の呼び出しでは、アンマネージコードから返される文字列は次のようなごちゃ混ぜの文字列です:øE〜。、Ê。これはエンコーディングに関係しているに違いないことは知っていますが、以下にリストしたいくつかのことを試しましたが、何も機能しません。これは、他の誰かが似たようなことをするために書いたVB.Netコードの問題ではありません。
これは私が試したものです: 1. [DllImport(" dmphnx32.dll")]を使用していますが、Charsetオプションをすべて試してみましたが成功しませんでした。
- 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
最初の2つの答えを試し、それらが役に立たないことを知った後、私は他の何かが疑わなければならないことを知りました。アプリのどこかで、アンマネージコードの初期化パラメーターが実際に欠落している小さなバグを見つけました。これにより、奇妙にエンコードされた文字列が発生していました。
助けてくれてありがとう、 コーリー
他のヒント
わかりました、あなたの問題がわかりました。 StringBuilder
に容量を割り当てる必要があります。デフォルトを使用することはできません。
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が機能するはずです。