【问题标题】:Can't get SAFEARRAY to work with Interop无法让 SAFEARRAY 与 Interop 一起工作
【发布时间】:2010-10-16 01:10:25
【问题描述】:

我有一个ATL COM Server,接口的方法是

STDMETHODIMP CWrapper::RUN(long iDataSize, SAFEARRAY** iData)

这个函数的 MIDL 看起来像

[id(1), helpstring("method RUN")] HRESULT RUN([in] long nSize, [in, size_is(nSize)] SAFEARRAY(_MyDataType*)* iData);

我使用 tlbimp 从该项目导入 tlb,因此我可以使用本机数组。然后我从 C# 中调用它,如下所示

 m_ServerWrapper.RUN(iInputs.Length,ref iInputs)

其中 Inputs 已经分配并填充了来自我的 C# 程序内部的另一个 COM 对象。现在,当我调用 C++ 包装器时,我的安全数组有一个BadPtr,并且从CWrapper::RUN 对后续 COM 对象的调用失败,数组没有进入最终的 dll。它显示为未分配。有谁知道我做错了什么?谢谢

编辑:我应该说该数组在 C# 中看起来很好。

EDIT2:调试器显示IDispatch* = 0x0000000 <Bad Ptr>, 5, 0x0000000 <Bad Ptr>({lpvtbl = 0xblahblah},... 的iData safearray。 所以看起来我的一些信息已经到达那里。

【问题讨论】:

  • IDL 中是否也定义了 _MyDataType?如果没有,你应该在那里做。另一件事:为什么需要 nSize? SAFEARRAY 保持自己的大小。

标签: c# c++ interop atl


【解决方案1】:

普通的 C# 数组与 SAFEARRAY 不同。我认为您必须自己制作:

[StructLayout(LayoutKind.Sequential)]
struct SafeArray
{
    public ushort   dimensions;  
    public ushort   features;    
    public uint     elementSize; 
    public uint     locks;       
    public IntPtr   dataPtr;     
    public uint     elementCount;
    public int      lowerBound;  
}

然后使用 Marshal.AllocCoTaskMem() 来创建内存。填写所有数据,然后传递。

【讨论】:

  • 我能找到的所有文档似乎都表明互操作层应该将数组编组为安全数组
猜你喜欢
  • 2020-02-29
  • 2011-04-25
  • 2014-11-22
  • 2014-05-15
  • 2019-11-27
  • 2017-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多