2012-08-06 58 views
0

我想馬歇爾下面的C++函數:如何馬歇爾在C#中的結構尺寸?

STDMETHODIMP CPushSource::SetSize(SIZE *pSize) 
{ 
    CMutexLock lock(&m_csShared); 
    CheckPointer(pSize, E_POINTER); 

    m_iImageWidth = pSize->cx; 
    m_iImageHeight = pSize->cy; 

    saveSettings(); 

    return S_OK; 
} 

與下面的C#代碼:

[ComImport, Guid("1b1afbaf-cb92-42da-8307-5a7be8c2b4b0")] 
public interface ISCFHSettings 
{ 
    [PreserveSig] 
    int SetSize([In, MarshalAs(UnmanagedType.Struct)] Size size); 
} 

我想用下面的代碼來調用它:

m_desktopFilter.SetSize(new Size(320,240)); 

我有點新本C++/C#互操作的東西,所以任何人誰可以點我在正確的方向是非常讚賞。

而且錯誤我的得到的是:

試圖讀取或寫入保護內存。這通常表明其他內存已損壞。

這是我嘗試一個簡單的DirectShow過濾器的包裝,如果重要。過濾器是SCFH-DSF。

我也試過

[ComImport, Guid("1b1afbaf-cb92-42da-8307-5a7be8c2b4b0")] 
public interface ISCFHSettings 
{ 
    [PreserveSig] 
    int SetSize([In, MarshalAs(UnmanagedType.Struct)] MySize size); 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct MySize 
{ 
    public int cx; 
    public int cy; 
} 

,並在調用代碼

MySize sz = new MySize(); 
sz.cx = 320; 
sz.cy = 240; 
m_desktopFilter.SetSize(sz); 

這也不會爲我工作。

[ComImport, Guid("1b1afbaf-cb92-42da-8307-5a7be8c2b4b0")] 
public interface ISCFHSettings 
{ 
    [PreserveSig] 
    int SetSize(ref MySize size); 
} 
+1

我有一種感覺,在C#中的Size結構是從一個你的C++函數需要不同的,因此,你可能需要創建一個明確的結構在C#中使用C++所期望的確切字段。 – Davio 2012-08-06 07:09:46

+0

我試過了,我有同樣的問題。我會讚揚這一嘗試。 – 2012-08-06 07:10:26

+0

用該代碼更新,同樣的錯誤。 – 2012-08-06 07:14:04

回答

1

[MarshalAs(UnmanagedType.Struct)]中的簽名不正確。該函數需要一個指向SIZE,所以你需要定義這個(你幹得)和傳引用,而無需使用額外的編組屬性。

我希望,你應該定義的界面是這樣的:

[ComImport, Guid("1b1afbaf-cb92-42da-8307-5a7be8c2b4b0")] 
public interface ISCFHSettings 
{ 

    int SetSize(MySize size); 

} 

[MarshalAs(UnmanagedType.Struct)]實際上是關係到VARIANT編組,但嚴重命名。

+0

對不起馬丁,我是一種新手,請你解釋如何通過參考傳遞它? – 2012-08-06 07:26:45

+0

@j_mcnally正如我在你的問題的評論中提到的,使用'ref':'int SetSize(ref MySize size);'(根據需要添加屬性)然後用'ref'調用它:var size = new尺寸(320240); m_desktopFilter.SetSize(ref size);' – hvd 2012-08-06 07:29:52

+0

@ hvd我用更多的代碼更新我的問題,但仍會拋出相同的錯誤。 – 2012-08-06 07:31:26

1

前面已經提到的,你應該能夠使其與ref工作,但因爲你還是有問題,這裏有一個最小的完整的程序,做的工作。你可以擴展,直到你得到你想要的東西。

C#:

using System.Diagnostics; 
using System.Runtime.InteropServices; 

namespace ConsoleApplication1 
{ 
    public struct mySize 
    { 
     public int x, y; 
    } 

    static class Program 
    { 
     [DllImport("ClassLibrary.dll")] 
     static extern int getX(ref mySize size); 

     static void Main(string[] args) 
     { 
      var size = new mySize { x=100, y=200 }; 
      int x = getX(ref size); 
      Debug.Assert(x == 100); 
     } 
    } 
} 

VC++:

struct mySize 
{ 
    int x, y; 
}; 

extern "C" __declspec(dllexport) 
int __stdcall getX(mySize *pSize) 
{ 
    return pSize->x; 
}