【问题标题】:How to marshal IDL struct containing SAFEARRAY of UDT to managed code如何将包含 UDT 的 SAFEARRAY 的 IDL 结构编组到托管代码
【发布时间】:2012-05-21 22:57:59
【问题描述】:

我有一个用这个 IDL 代码定义的 COM 库:

struct T_GPSParamsMap
{
  BSTR  Key;
  BSTR  Value;    
}T_GPSParamsMap;


struct T_FwClient
{
  BSTR                      Alias;
  SMSFilterActionEnum       Action;
  BSTR                      Text;
  int                       ToCall;
  int                       ToState;
  SAFEARRAY(T_GPSParamsMap) GpsData;
} T_FwClient;


struct T_SMSAction
{
  int                       ActionID;
  SMSFilterActionEnum       Action;
  BSTR                      Text;
  BSTR                      Folder;
  BSTR                      DestAddress;
  int                       ToCall;
  int                       ToState;
  SAFEARRAY(T_GPSParamsMap) GpsData;

  VARIANT_BOOL          forwardToNotListed;
  SAFEARRAY(T_FwClient) FwClients;

} T_SMSAction;

[
object,
uuid(F7942BCA-5122-46BB-94DB-89F5071842E4),
dual,
oleautomation,
nonextensible,
helpstring("ISMSFilter Interface"),
pointer_default(unique)
]
interface ISMSFilterWrapper : IDispatch{
  [id(1), helpstring("method GetFilterResult")] 
  HRESULT Init([in] BSTR schema_file_path, [out, retval] long* pVal);

  [id(2), helpstring("method GetFilterResult")] 
  HRESULT ApplyFilter([in] T_SMS* sms, [out, retval] long* pVal);

  [id(3), helpstring("method GetFilterResult")] 
  HRESULT GetFilterResult([in, out] T_SMSAction* ret_val, [out, retval] long* pVal);
};

现在,我在c#中是这样使用的:

SMSFilterLib.T_SMS smsFilter = new SMSFilterLib.T_SMS();
SMSFilterLib.T_SMSAction smsRule = new SMSFilterLib.T_SMSAction();

smsFilter.CalledParty = Convert.ToString(RadioID);
smsFilter.CallingParty = "1";
smsFilter.Text = Text;

m_smsFilter.ApplyFilter(ref smsFilter);

int RV = m_smsFilter.GetFilterResult(ref smsRule);

最后一行引发异常(从意大利语翻译):

HResult = -2146233054

“System.TypeLoadException”类型的第一次机会异常无法 编组“SMSFilterLib.T_SMSAction”类型的归档 GpsData:否 支持这种类型的编组。

这个 COM 库用于旧的 VB6 应用程序并且运行良好..

我已经使用 Visual Studio 的标准 CCW 将它导入到 c# 中(通过引用添加它),但它可能需要自定义 CCW。

谁能给我一些如何使用它的建议?

问候, 丹尼尔

【问题讨论】:

    标签: c# c++ com marshalling atl


    【解决方案1】:

    要使用 Visual Studio“添加引用窗口”添加 COM 引用,请使用 tlbimp.exe 创建一个互操作程序集

    当通过 Visual Studio 添加 COM 库时,它会通过 tlbimp 创建其定义,并将“将 SAFEARRAY 导入为 System.Array”的开关 /sysarray 传递给它。

    不要使用VS,而是手动使用tlbimp而不通过那个开关:

    tlbimp.exe COM_DLL_NAME.dll /out:INTEROP_ASSEMBLY_NAME.dll

    它会创建专门的类型化数组:

      [Guid("4162E179-7E99-4783-95D9-DA9A0B3BE568")]
      public struct T_SMSAction
      {
        public SMSFilterActionEnum Action;
        public int ActionID;
        public string DestAddress;
        public string Folder;
        public short forwardToNotListed;
        public T_FwClient[] FwClients;
        public T_GPSParamsMap[] GpsData;
        public string Text;
        public int ToCall;
        public int ToState;
      }
    

    问候。

    【讨论】:

      猜你喜欢
      • 2019-06-28
      • 2012-09-14
      • 2015-10-26
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多