2012-09-24 5 views
0

는 전 C# 정적 메서드 호출을 통해 관리되는 코드에서 소모품으로 C++WRL (Windows 런타임 C++ 템플릿 라이브러리)을 사용하여 WinRT 구성 요소를 만들려고합니다.만들기 WinRT 구성 요소 ++/WRL

int sum = Math.FastAdd(5,6); 

나를 위해 작동하지 않는 구현은 다음과 같습니다.
무엇이 잘못 될 수 있습니까? IDL 파일에서

  1. 수학 클래스를 만들 수 있습니다. 그것은 관리 측면에서 정적 메소드를위한 호스트가 될 것입니다. IMathStatics 인터페이스를 FastAdd 메서드로 생성하십시오. 여기에는 정적 메서드가 많이 포함되어 있습니다. 정적 속성이있는 클래스는 IMathStatics 인 수학 클래스입니다.
 

    import "inspectable.idl"; 
    #define COMPONENT_VERSION 1.0 
    namespace WRLNativeComponent 
    { 
     runtimeclass Math; 
     [uuid(EFA9D613-BA8F-4F61-B9E7-C6BE7B7765DD)] 
     [exclusiveto(WRLNativeComponent.Math)] 
     [version(COMPONENT_VERSION)] 
     interface IMathStatics : IInspectable 
     { 
      HRESULT FastAdd([in] int a, [in] int b, [out, retval] int* value); 
     } 
     [uuid(650438BA-C401-49E1-8F06-58DCD5A4B685), version(COMPONENT_VERSION)] 
     interface IMath : IInspectable 
     { 
      HRESULT InstanceMethod(void); 
     } 
     [static(WRLNativeComponent.IMathStatics, COMPONENT_VERSION)] 
     [version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)] 
     runtimeclass Math 
     { 
      [default] interface IMath; 
     } 
    } 
  1. MathStatics C++ 클래스를 만듭니다. InspectableClassStatic 매크로가 을 가리 키도록합니다. IMathStatics 문자열 식별자. ActivatableStaticOnlyFactory 매크로를 추가하여 MathStatics 클래스 구현을 가리 키도록하십시오.
 

    #pragma once 
    #include <wrl.h> 
    #include "MyMath_h.h" // generated from IDL 
    using namespace Microsoft::WRL; 
    namespace WRLNativeComponent { 
    class Math : public Microsoft::WRL::RuntimeClass, 
     ABI::WRLNativeComponent::IMath> 
    { 
     InspectableClass(RuntimeClass_WRLNativeComponent_Math, BaseTrust); 
    public: 
     Math(void) {} 
     ~Math(void) {} 
     STDMETHODIMP InstanceMethod() override 
     { 
      return S_OK; 
     } 
    }; 
    class MathStatics : public Microsoft::WRL::ActivationFactory 
    { 
     InspectableClassStatic(InterfaceName_WRLNativeComponent_IMathStatics, BaseTrust); 
    public: 
     MathStatics(void) {} 
     ~MathStatics(void) {} 
     STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) override 
     { 
      if (value == nullptr) return E_POINTER; 
      *value = a + b; 
      return S_OK; 
     } 
    }; 
    ActivatableClass(Math); 
    ActivatableStaticOnlyFactory(MathStatics); 
    } 
  1. 컴파일 후 파일이 생성됩니다 WRLNativeComponent.winmd. 나는 public static FastAdd 메서드를 사용하여 수학 클래스를 볼 수 있습니다.

  2. 정적 메서드를 호출하는 C# 클라이언트를 생성합니다. 호출이 이루어지면 'System.InvalidCastException'이 발생합니다. 이것은 올바르게 작동 할 것으로 예상됩니다.

답변

3

런타임 클래스에는 하나 이상의 활성화 팩토리가있을 수 있습니다. Activatable 매크로 중 하나를 사용할 때마다 런타임 유형에 대한 활성화 팩토리가 등록됩니다. 따라서, 라이브러리에서 다음 코드는

ActivatableClass(Math); 
ActivatableStaticOnlyFactory(MathStatics); 

시도는 두 개의 정품 인증 공장 등록 : 첫 번째는 Math 클래스와 두 번째 레지스터 실제로 사용할 수 없습니다 또 다른 간단한 활성화를 공장에 대한 간단한 정품 인증 공장 등록 (우리가 ' 왜 그 순간에 볼 수 있겠는가).

첫 번째 간단한 활성화 팩토리는 Math 클래스와 연결되어 있기 때문에 C# 구성 요소가 정적 멤버 함수를 호출하려고 시도하면 반환됩니다. 그런 다음 C# 구성 요소는이 인터페이스 포인터를 IMathStatics 인터페이스로 캐스팅하려고 시도합니다.이 인터페이스는 간단한 활성화 팩토리가 구현하지 않으므로 캐스팅이 실패하고 InvalidCastException이됩니다.


만 주어진 런타임 클래스에 대한 하나 개의 활성화 공장이있을 수 있기 때문에, 당신의 MathStatics 클래스는 IMathStatics 정적 멤버 인터페이스이가 필요합니다 (기본 건설에 사용되는 IActivationFactory 인터페이스를 모두 구현해야 당신 때문에 팩터 리 인터페이스 이름없이 activatable 속성을 사용하여 Math 유형을 기본 구성 가능으로 선언했습니다.

정품 인증 공장과 같이 구현 될 필요가있다 :

class MathStatics : public ActivationFactory<IMathStatics> 
{ 
    InspectableClassStatic(RuntimeClass_WRLNativeComponent_Math, BaseTrust); 

public: 

    MathStatics() {} 
    ~MathStatics() {} 

    STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) override 
    { 
     return MakeAndInitialize<Math>(ppvObject); 
    } 

    STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) override 
    { 
     if (value == nullptr) return E_POINTER; 
     *value = a + b; 
     return S_OK; 
    } 
}; 

ActivatableClassWithFactory(Math, MathStatics); 

ActivationFactory 기본 클래스 템플릿은 IActivationFactory 인터페이스의 기본 구현을 제공합니다. 이 기본 구현은 클라이언트가 Math 유형의 인스턴스를 기본으로 만들려고 할 때 E_NOTIMPL을 반환하기 때문에이 멤버 함수를 재정의하여 실제로 기본으로 Math 객체를 생성해야합니다. 정품 인증 공장 IInspectable의 이행을 완료 InspectableClassStatic를 사용하는 경우, 클래스 이름 (이 경우, RuntimeClass_WRLNativeComponent_Math에서) 런타임 클래스의 이름되어야한다는

참고 정적 인터페이스의 이름이 아닌. 활성화는 유형 이름별로 수행되며 WRL 인프라에서 이름을 사용하여 런타임 유형에 대한 활성화 팩토리를 조회하는 데 사용되는 이름입니다.

ActivatableClassWithFactory은 연관된 활성화 팩토리와 함께 런타임 클래스를 등록하는 데 사용됩니다.

관련 문제