简体   繁体   English

如何将包含UDT的SAFEARRAY的IDL结构编组为托管代码

[英]How to marshal IDL struct containing SAFEARRAY of UDT to managed code

I have a COM library defined with this IDL code: 我有一个使用此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);
};

Now, I use it in c# in this way: 现在,我以这种方式在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);

The last line raise an exception (translated from italian): 最后一行引发一个异常(从意大利语翻译):

HResult = -2146233054 HResult = -2146233054

first-chance exception of type 'System.TypeLoadException' Unable to marshal the filed GpsData of type 'SMSFilterLib.T_SMSAction': no support of marshaling available for this type. “ System.TypeLoadException”类型的第一次机会异常无法封送“ SMSFilterLib.T_SMSAction”类型的已归档GpsData:此类型不支持封送处理。

This COM library is used in old VB6 application and works well.. 该COM库用于旧的VB6应用程序中,并且运行良好。

I've imported it in c# using the standard CCW of Visual studio (adding it through references) but maybe it need to have a custom CCW. 我已经使用Visual Studio的标准CCW在c#中将其导入(通过引用将其添加),但也许它需要具有自定义CCW。

Can someone give me some suggestions how to use it? 有人可以给我一些使用建议吗?

Regards, Daniele 问候,丹妮尔

Instead to add the COM reference with the Visual Studio "Add Reference Windows", create an interop assembly with tlbimp.exe 而是使用Visual Studio“添加引用Windows”添加COM引用,而是使用tlbimp.exe创建一个互操作程序集

When a COM library is added through Visual Studio, it create its definition via tlbimp passing to it the switch /sysarray which "Import SAFEARRAY as System.Array". 通过Visual Studio添加COM库时,它将通过tlbimp创建定义,将传递给/ sysarray的开关“导入SAFEARRAY作为System.Array”传递给它。

Instead of using VS, use tlbimp by hand without to pass that switch: 无需使用VS,而无需通过该开关即可手动使用tlbimp:

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

and it will creates specialized typed arrays: 它将创建专门的类型化数组:

  [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;
  }

Regards. 问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM