2015-04-21 2 views
0

Я использую библиотеку ATL C++. Методы в файле IDL объявлены с параметром IQTAction, но когда я использую эту библиотеку типов в .NET Я получаю параметры методы типа QTAction НЕ IQTAction:Скомпилировать dll с использованием ATL с параметром метода в качестве интерфейсов, но получить их как coclasses

namespace COMTest3Lib 
{ 
    [ClassInterface(0)] 
    [Guid("C6DD8D8E-8375-4CA6-8534-007776D96215")] 
    [TypeLibType(2)] 
    public class QTTestClass : IQTTest, QTTest 
    { 
     public QTTestClass(); 
     public virtual void GetActiveAction(out QTAction pActionOut); 
     public virtual void RunAction(QTAction pActionIn); 
    } 
} 

namespace COMTest3Lib 
{ 
    [CoClass(typeof(QTActionClass))] 
    [Guid("FBCC87D9-4E5C-40D2-853F-E8548E625C5B")] 
    public interface QTAction : IQTAction 
    { 
    } 
} 

Почему это? Как заставить его использовать интерфейс вместо класса в качестве типа параметра?

Вот мой заголовок и IDL файлы:

using namespace ATL; 

//QTTest.h 
class ATL_NO_VTABLE CQTTest : 
    public CComObjectRootEx<CComSingleThreadModel>, 
    public CComCoClass<CQTTest, &CLSID_QTTest>, 
    public IDispatchImpl<IQTTest, &IID_IQTTest, &LIBID_COMTest3Lib, /*wMajor =*/ 1, /*wMinor =*/ 0> 
{ 
public: 
    CQTTest() 
    { 
     m_pActiveAction.CoCreateInstance(CLSID_QTAction); //construct an action; 
    } 

DECLARE_REGISTRY_RESOURCEID(IDR_QTTEST) 


BEGIN_COM_MAP(CQTTest) 
    COM_INTERFACE_ENTRY(IQTTest) 
    COM_INTERFACE_ENTRY(IDispatch) 
END_COM_MAP() 

    DECLARE_PROTECT_FINAL_CONSTRUCT() 

    HRESULT FinalConstruct() 
    { 
     return S_OK; 
    } 

    void FinalRelease() 
    { 
     ::MessageBox(NULL, L"#################QTTest is being disposed", L"info", 0); 
    } 

public: 
    STDMETHOD(GetActiveAction)(/*out*/IQTAction** pActionOut); 
    STDMETHOD(RunAction)(/*in*/IQTAction* pActionIn); 

private: 
    CComPtr<IQTAction> m_pActiveAction; 
}; 

OBJECT_ENTRY_AUTO(__uuidof(QTTest), CQTTest) 

IDL FILE:

import "oaidl.idl"; 
import "ocidl.idl"; 
[ 
    object, 
    uuid(FBCC87D9-4E5C-40D2-853F-E8548E625C5B), 
    pointer_default(unique) 
] 
interface IQTAction : IDispatch{ 
    [helpstring("method Run")] HRESULT Run(void); 
}; 
[ 
    object, 
    uuid(19F205D2-1D1C-4DB7-A731-498665CC297F), 
    version(1.0) 
] 
interface IQTTest : IDispatch{ 
    [helpstring("method GetActiveAction")] HRESULT GetActiveAction([out] IQTAction** pActionOut); 
    //[helpstring("method Run")] HRESULT Run(void); 
    [helpstring("Run a specific action")] HRESULT RunAction([in] IQTAction* pActionIn); 
}; 
[ 
    uuid(0E651E25-832E-4410-9A9E-F8CD8574F4D8), 
] 
library COMTest3Lib 
{ 
    importlib("stdole2.tlb"); 
    [ 
     uuid(C6DD8D8E-8375-4CA6-8534-007776D96215)  
    ] 
    coclass QTTest 
    { 
     [default] interface IQTTest; 
    }; 
    [ 
     uuid(72D899CC-7722-4260-A441-3D1225132019)  
    ] 
    coclass QTAction 
    { 
     [default] interface IQTAction; 
    }; 
}; 
+1

Почему пустые голоса и близкие голоса? Если вы не понимаете оп, спросите его подробности. Для меня ясно, что задается вопросом: почему тип класса 'QTAction' .NET используется в методах' IQTTest' вместо типа интерфейса IQTAction' .NET? – acelent

+1

'IQTAction' реализуется только QTAction в библиотеке типов. .NET interop видит это и «объединяет» определения, пытаясь упростить вещи. Тем не менее, вы видите его как «QTAction» на стороне .NET, он по-прежнему является интерфейсом «IQTAction». –

ответ

1

Насколько я знаю, библиотека типа импортер использует интерфейс CoClass вместо фактического интерфейса когда обнаруживается, что есть только один компонент, реализующий этот интерфейс как значение по умолчанию в пределах той же библиотеки типов, и нет способа предотвратить это.

Однако, обратите внимание, что QTTest и IQTTest оба интерфейсы, с тем же Guid и методы. Но QTTest имеет дополнительный атрибут, CoClassAttribute(QTTestClass), который позволяет компилятору Microsoft C# скомпилировать new QTTest() в new QTTestClass().

Это жонглирование tlbimp.exe позволяет программистам VB6 чувствовать себя как дома, но это довольно странно для разработчиков на C++. В вашем случае это подразумевает литье между двумя другими эквивалентными типами интерфейсов.

+1

Я хочу отметить, что TLBIMP.exe также не будет генерировать 'QTTest' (интерфейс coclass), если он не находится в библиотеке того же типа, что и компонент, реализующий его, он будет генерировать необработанный интерфейс (' IQTTest'). – Nmktronas

+0

Спасибо за примечание, я отредактировал ответ соответственно. – acelent