【问题标题】:Can I simplify method signatures I am not using in a ComImport?我可以简化未在 ComImport 中使用的方法签名吗?
【发布时间】:2018-05-13 20:40:46
【问题描述】:

我正在尝试在IWiaDevMgr2 上致电GetImageDlg。有许多相当复杂的方法(我没有使用)引用了许多类型(我也没有使用)。由于我找不到用于自动生成 ComImport 的 TLB 或 IDL,因此我宁愿避免手动翻译所有引用的类型。

我可以通过替换来“跳过”方法和类型

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2
{
    IEnumWIA_DEV_INFO EnumDeviceInfo(
        int lFlags);

    IWiaItem2 CreateDevice(
        int lFlags,
        [MarshalAs(UnmanagedType.BStr)] string bstrDeviceID);

    // ...snip five other method declarations...

    IWiaItem2 GetImageDlg(
        int lFlags,
        [MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
        IntPtr IntPtrParent,
        [MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
        [MarshalAs(UnmanagedType.BStr)] string bstrFilename,
        /* [out] */ out int plNumFiles,
        /* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);

};

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
    void VTablePlaceholder0();
    void VTablePlaceholder1();
    void VTablePlaceholder2();
    void VTablePlaceholder3();
    void VTablePlaceholder4();
    void VTablePlaceholder5();
    void VTablePlaceholder6();

    [return: MarshalAs(UnmanagedType.Interface)]
    object GetImageDlg(
        int lFlags,
        [MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
        IntPtr IntPtrParent,
        [MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
        [MarshalAs(UnmanagedType.BStr)] string bstrFilename,
        /* [out] */ out int plNumFiles,
        /* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);

};

一切似乎都可以正常工作,只要我不调用任何占位符。我可以这样做没有后果吗?

【问题讨论】:

    标签: c# com pinvoke com-interop


    【解决方案1】:

    当然可以。你是唯一会使用这个接口定义的人,所以没关系。

    当然,如果这个接口被用作从本地到托管的回调,那将是一个问题,但在这种情况下,你会以某种方式实现它。实现这样的虚拟方法是未来问题的标志。

    请注意,有一种官方的做法。您可以为占位符使用特殊的 _VtblGap{0}_{1} 名称,其中 0 是索引,1 是要跳过的方法数。

    在此处查看 Roslyn 中的实现(它也在公共语言基础设施规范中):https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/ModuleExtensions.cs

            // From IMetaDataEmit::DefineMethod documentation (http://msdn.microsoft.com/en-us/library/ms230861(VS.100).aspx)
            // ----------------------
            // In the case where one or more slots need to be skipped, such as to preserve parity with a COM interface layout, 
            // a dummy method is defined to take up the slot or slots in the v-table; set the dwMethodFlags to the mdRTSpecialName 
            // value of the CorMethodAttr enumeration and specify the name as:
            //
            // _VtblGap<SequenceNumber><_CountOfSlots>
            //
            // where SequenceNumber is the sequence number of the method and CountOfSlots is the number of slots to skip in the v-table. 
            // If CountOfSlots is omitted, 1 is assumed.
            // ----------------------
            //
            // From "Partition II Metadata.doc"
            // ----------------------
            // For COM Interop, an additional class of method names are permitted:
            // _VtblGap<SequenceNumber><_CountOfSlots>
            // where <SequenceNumber> and <CountOfSlots> are decimal numbers
            // ----------------------
    

    所以在你的情况下,它会是:

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
    public interface IWiaDevMgr2_Fake
    {
        void _VtblGap1_7(); // skip seven methods
    
        ...
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-28
      • 2018-04-18
      • 2019-11-04
      • 2021-04-12
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 2014-12-22
      相关资源
      最近更新 更多