2012-08-06 62 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; 
}