2

次の関数を DllImport したいと思います。それにもかかわらず、「ret」は true を返しますが、私の文字列配列は空のように見えるので、マーシャリングが必要かもしれません。どんなヒントでも大歓迎です!前もって感謝します :)

C 関数:

bool getBootLog(char **a1);

以下のコードはテスト用であり、正しく動作しません。

DllImport:

[DllImport("ext.dll")]
public static extern bool getBootLog(string[] bootLog);

現在のコード:

        string[] bootLog = new string[1024 * 1024];
        bool ret = getBootLog(bootLog);

        foreach (string s in bootLog)
        {
            Debug.WriteLine(s);
        }

うまくいかない2回の試行:

var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
try
{
    getBootLog(out ptr);
    var deref1 = (string)Marshal.PtrToStringAnsi(ptr);
    Debug.WriteLine(deref1);
}
finally
{
    Marshal.FreeHGlobal(ptr);
}

var ptr2 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
try
{
    getBootLog(out ptr2);
    var deref1 = (IntPtr)Marshal.PtrToStructure(ptr2, typeof(IntPtr));
    var deref2 = (string[])Marshal.PtrToStructure(deref1, typeof(string[]));
    Debug.WriteLine(deref2);
}
finally
{
    Marshal.FreeHGlobal(ptr2);
}

モーセンのアイデア:

[DllImport("Ext.dll")]
public static extern bool getBootLog(StringBuilder bootLog);

try
{
    int bufferSize = 50;
    StringBuilder bootLog = new StringBuilder(" ", bufferSize);
    Debug.WriteLine("Prepared bootLog...");
    getBootLog(bootLog);
    Debug.WriteLine("Bootlog length: " + bootLog.Length);
    string realString = bootLog.ToString();
    Debug.WriteLine("Bootlog: " + realString);
}
catch(Exception ex)
{
    Debug.WriteLine("Xception: " + ex.ToString());
}

結果:

準備された bootLog... ブートログの長さ: 0 ブートログ:

4

1 に答える 1

0

宣言を修正します。

[DllImport("ext.dll", CharSet = CharSet.Ansi)]
public static extern bool getBootLog(ref IntPtr bootLogPtr);

編集されたバージョンのコードで試行された行は正しくないようです。

var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));

実際には、バッファのサイズを指定する必要があります。

var ptr = Marshal.AllocHGlobal(100); // Set it to 100 bytes, maximum!

ptrC スタイルの null で終了する文字列として、に長さを書き込みます。

Marshal.WriteByte(ptr, 100, 0);

次に、頭のてっぺんになる呼び出しを呼び出します。

IntPtr ptrBuf = ptr;
getBootLog(ref ptrBuf);

バッファの内容をptrBuf文字列変数にコピーします。

string sBootLog = Marshal.PtrToStringAnsi(ptrBuf);

アンマネージ メモリの内容をクリーンアップします。

Marshal.FreeHGlobal(ptr);
于 2016-05-30T21:52:06.967 に答える