3

次のことについて助けが必要です。私は C++ API (ソースへのアクセスなし) を持っていますが、char* 属性を返すメソッド、または char* 属性を含む構造体を返すことに苦労しています。API のドキュメントによると、戻り値は次のとおりです。

戻り値
関数が成功した場合、戻り値は、ホスト システム上のプロジェクトごとに 1 つずつ、2 番目の null 文字で終わる、一連の null で終わる文字列へのポインタです。<null>次の例は、終端のヌル文字を表すバッファーの内容を示しています。

project1<null>project2<null>project3<null><null>

関数が失敗した場合、戻り値は NULL です

私が抱えている問題は、C# で返されたポインターに最初の値しか含まれていないことです...この場合は project1 です。管理された側でそれらをループできるように完全なリストを取得するにはどうすればよいですか?

C# コードは次のとおりです。

    [DllImport("vmdsapi.dll", EntryPoint = "DSGetProjectList", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr DSGetProjectList();

呼び出し方法:

   IntPtr ptrProjectList = DSAPI.DSGetProjectList();
   string strProjectList = Marshal.PtrToStringAnsi(ptrProjectList).ToString();

strProjectList には最初の項目のみが含まれます。
APIのヘッダーファイルからの情報は次のとおりです...

   DllImport char *DSGetProjectList dsproto((void));

これは、テスト目的で使用した C++ コンソール アプリのサンプル コードです...

   char *a;
   a = DSGetProjectList( );
   while( *a ) { 
    printf("a=%s\n", a); 
    a += 1 + strlen(a); 
   } 

各反復により、リスト内のすべてのプロジェクトが正しく表示されます。

4

2 に答える 2

2

問題は、 を使用して C++ char* を C# 文字列に変換するときにMarshal.PtrToStringAnsi、最初のヌル文字で停止することです。

を文字列に直接変換しないでくださいchar*

char*によって表されるIntPtrbyte[]usingにコピーして、必要な数の文字列を抽出することもできます(マネージド配列から文字列を抽出するためのMatthew Watsonの回答Marshal.Copyを参照してください) が、最初に複数文字列のサイズを取得する必要があります。

leppieが示唆するように、最初の文字列を抽出してから、この文字列サイズでポインターをインクリメントし、次の文字列を抽出することもできますMarshal.PtrToStringAnsi。(最後の NULL 文字から) 空の文字列が抽出されると停止します。

何かのようなもの :

IntPtr ptrProjectList = DSAPI.DSGetProjectList();
List<string> data;
string buffer;
do {
    buffer = Marshal.PtrToStringAnsi(ptrProjectList);
    ptrProjectList += buffer.size() + 1;
    data.Add(buffer);
}while(buffer.size() > 0)
于 2013-04-17T11:44:42.213 に答える
0

この種の文字列は a と呼ばMulti-Stringれ、Windows API では非常に一般的です。

それらをマーシャリングするのは面倒です。あなたがしなければならないことは、char[]それを文字列ではなく配列としてマーシャリングしてから、char[]配列を文字列のセットに変換することです。

ソリューションの例については、こちらを参照してください。関連するコードをこの回答にコピーしましたが、指定したリンクからコピーされています。

static List<string> MultiStringToList(char[] multistring)
{
    var stringList = new List<string>();
    int i = 0;

    while (i < multistring.Length)
    {
        int j = i;

        if (multistring[j++] == '\0') 
            break;

        while (j < multistring.Length)
        {
            if (multistring[j++] == '\0')
            {
                stringList.Add(new string(multistring, i, j - i - 1));
                i = j;
                break;
            }
        }
    }

    return stringList;
}
于 2013-04-17T11:56:13.910 に答える