【问题标题】:How to marshall a SIZE structure in C#?如何在 C# 中编组 SIZE 结构?
【发布时间】:2012-08-06 07:06:19
【问题描述】:

我正在尝试编组以下 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);
}

【问题讨论】:

  • 我感觉 C# 中的 Size 结构与您的 C++ 函数所期望的不同,因此您可能需要在 C# 中创建一个具有 C++ 期望的确切字段的显式结构。跨度>
  • 我试过了,我遇到了同样的问题。我会修改那个尝试。
  • 用该代码更新,同样的错误。
  • MarshalAs(UnmanagedType.Struct) 看起来不对。您的 C++ 函数采用指针,而不是结构。您可以尝试将size 设为ref 参数吗?
  • 哦,实际上,更糟糕的是:根据文档,MarshalAs(UnmanagedType.Struct) 与结构根本没有任何关系...

标签: c# c++ interop com-interop


【解决方案1】:

签名中的[MarshalAs(UnmanagedType.Struct)] 不正确。该函数需要一个指向 SIZE 的指针,因此您需要定义它(就像您所做的那样)并通过引用传递它,而不使用其他编组属性。

我希望您应该像这样定义接口:

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

    int SetSize(MySize size); 

}

[MarshalAs(UnmanagedType.Struct)] 实际上与 VARIANT 编组有关,但命名错误。

【讨论】:

  • 对不起马丁,我是个新手,你能解释一下如何通过引用传递它吗?
  • @j_mcnally 正如我在对您的问题的评论中提到的,使用refint SetSize(ref MySize size);(根据需要添加属性)然后也使用refvar size = new Size(320,240); m_desktopFilter.SetSize(ref size); 调用它跨度>
  • @hvd 我已经用更多仍然抛出相同错误的代码更新了我的问题。
  • 谢谢,马丁,这不是同样的内存损坏错误。我现在尝试使用和不使用 ref。没有任何效果,我希望有任何其他想法。
【解决方案2】:

如前所述,您应该能够使用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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    相关资源
    最近更新 更多