2012-07-25 50 views
2

有C++方法,具有以下特徵:我如何馬歇爾字符指針數組[256]從C++到C#

typedef char TNameFile[256]; 

void Foo(TNameFile** output); 

我已經江郎才盡瞭如何馬歇爾它。

+0

爲什麼要有一個指向數組的指針?似乎至少有一個是不必要的。可能兩者,在這種情況下,數組也可能是返回值。 – millimoose 2012-07-25 09:25:25

+0

@millimoose它是指向在Foo內創建的TNameFile的輸出數組的指針。這是第三方圖書館。 – Redwan 2012-07-25 09:32:28

+1

使用'static extern void Foo(IntPtr output)',然後使用'Marshal'類來遍歷數組並讀取內容 – 2012-07-25 09:53:17

回答

1

假設他們返回一個空字符串作爲最後一個元素:

static extern void Foo(ref IntPtr output); 

IntPtr ptr = IntPtr.Zero; 
Foo(ref ptr); 
while (Marshal.ReadByte(ptr) != 0) 
{ 
    Debug.Print(Marshal.PtrToStringAnsi(ptr, 256).TrimEnd('\0')); 
    ptr = new IntPtr(ptr.ToInt64() + 256); 
} 

編輯:既然我已經寫在我的智能手機上面的代碼,我今天早上測試的代碼,它看起來像它應該工作(我只需要添加TrimEnd('\0'))。這裏是我的測試案例:

class Program 
{ 
    const int blockLength = 256; 

    /// <summary> 
    /// Method that simulates your C++ Foo() function 
    /// </summary> 
    /// <param name="output"></param> 
    static void Foo(ref IntPtr output) 
    { 
     const int numberOfStrings = 4; 
     byte[] block = new byte[blockLength]; 
     IntPtr dest = output = Marshal.AllocHGlobal((numberOfStrings * blockLength) + 1); 
     for (int i = 0; i < numberOfStrings; i++) 
     { 
      byte[] source = Encoding.UTF8.GetBytes("Test " + i); 
      Array.Clear(block, 0, blockLength); 
      source.CopyTo(block, 0); 
      Marshal.Copy(block, 0, dest, blockLength); 
      dest = new IntPtr(dest.ToInt64() + blockLength); 
     } 
     Marshal.WriteByte(dest, 0); // terminate 
    } 

    /// <summary> 
    /// Method that calls the simulated C++ Foo() and yields each string 
    /// </summary> 
    /// <returns></returns> 
    static IEnumerable<string> FooCaller() 
    { 
     IntPtr ptr = IntPtr.Zero; 
     Foo(ref ptr); 
     while (Marshal.ReadByte(ptr) != 0) 
     { 
      yield return Marshal.PtrToStringAnsi(ptr, blockLength).TrimEnd('\0'); 
      ptr = new IntPtr(ptr.ToInt64() + blockLength); 
     } 
    } 

    static void Main(string[] args) 
    { 
     foreach (string fn in FooCaller()) 
     { 
      Console.WriteLine(fn); 
     } 
     Console.ReadKey(); 
    } 
} 

還有一個問題:誰去釋放緩衝區?

+0

你有沒有時間去測試它? – 2012-07-31 15:47:04

0

它將使你的生活,如果你使用C++/CLI,而不是本地C++輕鬆了很多,你會不會擔心不安全的代碼和marhsalling:

array<Byte>^ cppClass::cppFunction(TNameFile** input, int size) 
{ 
    array<Byte>^ output = gcnew array<Byte>(size); 

    for(int i = 0; i < size; i++) 
     output[i] = (**input)[i]; 

    return output; 
} 

如果你必須使用編組再試試WouterH在他的回答中使用Marshal.PtrToStringAnsi