Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Наследование ComObject интерфейсов и назначение аттрибутов

#c_sharp #net #com #interop


Есть ли необходимость повторно указывать аттрибут типа интерфейса Com, если он наследуется
от другого Com интерфейса, в котором уже был задан тип?

Пример:

[ComImport]
[Guid("aec22fb8-76f3-4639-9be0-28eb43a67a2e")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDXGIObject
{
    long SetPrivateData([In] ref Guid name, [In] uint dataSize, IntPtr dataPtr);

    long SetPrivateDataInterface([In] ref Guid name, [In] [MarshalAs(UnmanagedType.IUnknown)]
        object unknownInterfaceObject);

    long GetPrivateData([In] ref Guid name, out int dataSize, out IntPtr dataPtr);

    long GetParent([In] ref Guid rIId, [Out] out object pParent);
}


Далее, его наследником будет IDXGIFactory:

///  />
/// 
///     An IDXGIFactory interface implements methods for generating DXGI objects
(which handle fullscreen transitions).
/// 
[ComImport]
[Guid("7b7166ec-21c7-44ae-b21a-c9ae321ae369")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDXGIFactory : IDXGIObject
{
    /// 
    ///     Enumerates the adapters (video cards).
    /// 
    [PreserveSig]
    HResult EnumAdapters(uint numAdapter, [MarshalAs(UnmanagedType.IUnknown)] out
object adapter);

    /// 
    ///     Allows DXGI to monitor an application's message queue for the alt-enter
key sequence (which causes the application
    ///     to switch from windowed to fullscreen or vice versa).
    /// 
    [PreserveSig]
    HResult MakeWindowAssociation(IntPtr windowHandle, uint flags);

    /// 
    ///     Get the window through which the user controls the transition to and
from fullscreen.
    /// 
    [PreserveSig]
    HResult GetWindowAssociation(out IntPtr outHandleWindow);

    /// 
    ///     Creates a swap chain.
    /// 
    [PreserveSig]
    HResult CreateSwapChain(IntPtr lpIUnknown, IntPtr ptr, out IntPtr outPtr);

    /// 
    ///     Create an adapter interface that represents a software adapter.
    /// 
    [PreserveSig]
    HResult CreateSoftwareAdapter(IntPtr moduleHandle, out IntPtr outPtr);
}


Есть ли необходимость вновь писать аттрибут

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]


для интерфейса наследника, если он тоже по сути является IUnknown?
    


Ответы

Ответ 1



Нужно, так как InterfaceTypeAttribute определен как не наследуемый: [System.AttributeUsage(System.AttributeTargets.Interface, Inherited=false)] [System.Runtime.InteropServices.ComVisible(true)] public sealed class InterfaceTypeAttribute : Attribute

Ответ 2



Путем некоторых манипуляций удалось выяснить, в обязательном порядке стоит соблюдать следующие правила: Наследуемый объект должен переопределять декларацию интерфейса от которого наследуется, перед методами текущего метода, т.е. до их объявлений. (Спасибо за подсказку @MSDN.WhiteKnight). Интерфейс наследник в обязательном порядке должен иметь атрибут [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)], иначе будем иметь проблемы с доступом к памяти. Интерфейс наследник наследуется от интерфейса который для него является базовым лишь для удобства работы с данными интерфейсами. Таким образом, базовый интерфейс к примеру в данном случае это IDXGIObject выглядит так: /// /// An IDXGIObject interface is a base interface for all DXGI objects; IDXGIObject supports associating caller-defined /// (private data) with an object and retrieval of an interface to the parent object. /// [Guid("aec22fb8-76f3-4639-9be0-28eb43a67a2e")] [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDXGIObject { /// /// Sets an IUnknown interface as private data; this associates application-defined data with the object. /// [PreserveSig] HResult SetPrivateData(ref Guid name, uint dataSize, IntPtr dataPtr); /// /// Set an interface in the object's private data. /// [PreserveSig] HResult SetPrivateDataInterface(ref Guid name, [MarshalAs(UnmanagedType.IUnknown)] object unknownInterfaceObject); /// /// Get a pointer to the object's data. /// [PreserveSig] HResult GetPrivateData(ref Guid name, out int dataSize, out IntPtr dataPtr); /// /// Gets the parent of the object. /// [PreserveSig] HResult GetParent(ref Guid rIId, out object pParent); } Далее от него к примеру наследуется IDXGIFactory определение необходимо задавать строго вот так: /// /// /// An interface implements methods for generating DXGI objects (which handle fullscreen /// transitions). /// [Guid("7b7166ec-21c7-44ae-b21a-c9ae321ae369")] [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDXGIFactory : IDXGIObject { /// /// Sets an IUnknown interface as private data; this associates application-defined data with the object. /// [PreserveSig] new HResult SetPrivateData(ref Guid name, uint dataSize, IntPtr dataPtr); /// /// Set an interface in the object's private data. /// [PreserveSig] new HResult SetPrivateDataInterface(ref Guid name, [MarshalAs(UnmanagedType.IUnknown)] object unknownInterfaceObject); /// /// Get a pointer to the object's data. /// [PreserveSig] new HResult GetPrivateData(ref Guid name, out int dataSize, out IntPtr dataPtr); /// /// Gets the parent of the object. /// [PreserveSig] new HResult GetParent(ref Guid rIId, out object pParent); /// /// Enumerates the adapters (video cards). /// [PreserveSig] HResult EnumAdapters(uint numAdapter, [MarshalAs(UnmanagedType.IUnknown)] out object adapter); /// /// Allows DXGI to monitor an application's message queue for the alt-enter key sequence (which causes the application /// to switch from windowed to fullscreen or vice versa). /// [PreserveSig] HResult MakeWindowAssociation(IntPtr windowHandle, uint flags); /// /// Get the window through which the user controls the transition to and from fullscreen. /// [PreserveSig] HResult GetWindowAssociation(out IntPtr outHandleWindow); /// /// Creates a swap chain. /// [PreserveSig] HResult CreateSwapChain(object iUnknown, ref DxgiSwapChainDesc swapChainDesc, [MarshalAs(UnmanagedType.IUnknown)] out object dxgiSwapChainObject); /// /// Create an adapter interface that represents a software adapter. /// [PreserveSig] HResult CreateSoftwareAdapter(IntPtr moduleHandle, out IntPtr outPtr); } Все проблемы себя исчерпали, и код стал работать так как должен.

Комментариев нет:

Отправить комментарий