2009-12-14 66 views
2

我在C#中有一個函數,它將結構數組傳遞給用C++編寫的DLL。該結構是一組整數,當我讀出DLL中的數據時,所有的值都可以正常顯示。但是,如果我嘗試從C++寫入元素,那麼當我嘗試讀取C#時,這些值永遠不會顯示出來。將值賦給C++結構中的值爲從C#傳遞的結構時出現問題#

C#

[StructLayout(LayoutKind.Sequential)] 
struct Box 
{ 
    public int x; 
    public int y; 
    public int width; 
    public int height; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct Spot 
{ 
    public int x; 
    public int y; 
} 

static void TestCvStructs() 
{ 
    int len = 100; 
    Box[] r = new Box[len]; 
    Spot[] p = new Spot[len]; 

    for (int i = 0; i < len; i++) 
    { 
    r[i].x = i*10; 
    r[i].y = i * 200; 
    r[i].width = r[i].x * 10; 
    r[i].height = r[i].y * 100 + r[i].x * 5; 

    p[i].x = i * 8; 
    p[i].y = i * 12; 
    } 

    PassCvStructs(len, r, p); 

    for (int i = 0; i < len; i++) 
    { 
    Console.WriteLine("Point/x:{0} Boxes/x{1}", p[i].x, r[i].x); 
    } 
} 

[DllImport(dll)] 
private static extern int PassSomeStructs(int count, Box[] boxes, Spot[] points); 

C++

typedef struct Box 
{ 
    int x; 
    int y; 
    int width; 
    int height; 
} Box; 

typedef struct Spot 
{ 
    int x; 
    int y; 
} Spot; 

CPPDLL_API int PassSomeStructs(int arrayLength, Box *boxes, Spot *points) 
{ 
    for(int i = 0; i < arrayLength; ++i) 
    { 
    printf("Group:%i\n", i); 
    printf("Rect - x:%i y:%i width:%i length:%i\n", boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height); 
    printf("Point - x:%i y:%i\n", points[i].x, points[i].y); 
    printf("\n"); 

    points[i].x = 3; 
    boxes[i].x = 1; 
    } 
    return 0; 
} 

回答

0

我發現張貼到另一個問題的答案:How to marshall array of structs in C#?

編組時顯然默認爲將參數編組爲In。否則,他們需要顯式聲明爲Out或In,Out。在明確指定我的代碼之後,示例現在可以工作。

感謝他的Skeetness爲答案和antonmarkov接觸到MarshalAs。

private static extern int PassSomeStructs(int count, [In, Out] Box[] boxes, [In, Out] Spot[] points); 
0

您是否嘗試過加入REF/out關鍵字到C#的extern?

另一個想法是試圖傳遞一個IntPtr而不是類本身,或把它在-as-一個IntPtr ...

我相信,結構被複制,而不是默認的引用傳遞。

老實說刺傷在黑暗中,但你沒有任何解答,所以希望這有助於...

互操作仍然是在「它的神奇」的階段對我來說...

+0

從行爲看,它看起來像它的傳遞參考。當我嘗試使用ref時,我在C++端獲得了瘋狂的值,就像這些值實際上是指針一樣。如果我將接收類型改爲指向指針的指針,我會得到一個內存訪問異常:(我打算將所有內容都打包到一個int數組中,並且通過這個,導致這個「Magic」讓我感到困惑。 – QueueHammer

1

從編組數組上的MDSN article:嘗試在數組類型上設置以下屬性。這通常用於從C++調用C#,但也可能需要將更新後的值傳回C#。

[DllImport(dll)] 
private static extern int PassSomeStructs(int count, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Box[] boxes, 
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Spot[] points); 

也看到這篇文章了成功的雙向編組的例子:

http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/ff0123d0-506b-4de2-bfb5-f690c9358826/

+0

在那裏,我們知道了與C#如何聲明extern有關係 –

+0

我可以使用LPArray以相同的結果使用SafeArray或ByValArray導致錯誤使用另一個值會產生一個錯誤,說明數組只能使用前三種類型。 – QueueHammer