2012-09-15 2 views
3

C++ 비 관리 코드에서 C# 메서드를 호출하고 있습니다. 배열에서 반환 된 클래스 인스턴스에서 값을 가져 오는 데 문제가 있습니다.E_NOINTERFACE 클래스 메서드 포인터를 가져 오는 중

나는이 문제가있는 방법입니다 코드를 조금

을 단순화했습니다.

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] 
    public ScOrder[] GetOrders() 
    { 
     return new ScOrder[] { 

      (new ScOrder(1), 
      (new ScOrder(2) 
     }; 
    } 

은 IScOrder 인터페이스

[ComVisible(true)] 
[Guid("B2B134CC-70A6-43CD-9E1E-B3A3D9992C3E")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IScOrder 
{ 
    long GetQuantity(); 
} 

입니다 그리고 이것은 내 previous request에서 Zdeslav Vojkovic에서 도움이 후 ScOrder 구현

[ComVisible(true)] 
[Guid("F739759E-4D00-440E-B0B7-69AAF97FCB6D")] 
[ClassInterface(ClassInterfaceType.None)] 
public class ScOrder 
{ 
    private long quantity = 0; 

    public ScOrder() {} 

    public ScOrder(long quantity) 
    { 
     this.quantity = quantity; 
    } 

    public long GetQuantity() 
    { 
     return this.quantity; 
    } 
} 

이것은 C++ 코드입니다. 문제는 설명에 설명되어 있습니다.

  • ATL도 MFC도 사용하고 있지 않습니다.
  • C++ tlb 파일은 regasm을 통해 생성됩니다.

COM 초기화와 GetOrders를 호출하는 방법은 내가 순서 내부 (펑크)를 디버깅 할 수 있다는 것을 발견, Zdeslav 좋은

IScProxyPtr iPtr; 
CoInitialize(NULL); 
iPtr.CreateInstance(CLSID_ScProxy); 
SAFEARRAY* orders; 
iPtr->GetOrders(&orders); 
LPUNKNOWN* punks; 
HRESULT hr = SafeArrayAccessData(orders, (void**)&punks); 
if(SUCCEEDED(hr)) 
{ 
    long lbound, ubound; 
    SafeArrayGetLBound(orders, 1, &lbound); 
    SafeArrayGetUBound(orders, 1, &ubound); 
    long elements = ubound - lbound + 1; 
    for(int i=0;i<elements;i++) 
    { 
     LPUNKNOWN punk = punks[i]; //the punk seems valid 
     IScOrderPtr order(punk); //unfortunatelly, "order" now points to {0x00000000} 

     //subsequent attempt to get the value will fail 
     long quantity = 0; 
     HRESULT procCall; 
     //GetQuantity will throw an exception 
     procCall = order->GetQuantity((long long *)q); 

    } 
    SafeArrayUnaccessData(orders); 
} 
SafeArrayDestroy(orders); 

감사를 작동합니다

IScOrderPtr order(punk); 

그래서 나는 들어갔다 주문 (펑크)을 통해 거기에서 무슨 일이 일어나고 있는지 확인할 수 있습니다. 나는 "comip.h"

// Constructs a smart-pointer from any IUnknown-based interface pointer. 
// 
template<typename _InterfaceType> _com_ptr_t(_InterfaceType* p) 
    : m_pInterface(NULL) 
{ 
    HRESULT hr = _QueryInterface(p); 

내부에있어 ... 나는 또한 comip.h에서 _QueryInterface (p)를 구현 내부 계단

// Performs a QI on pUnknown for the interface type returned 
// for this class. The interface is stored. If pUnknown is 
// NULL, or the QI fails, E_NOINTERFACE is returned and 
// _pInterface is set to NULL. 
// 
template<typename _InterfacePtr> HRESULT _QueryInterface(_InterfacePtr p) throw() 
{ 
    HRESULT hr; 

    // Can't QI NULL 
    // 
    if (p != NULL) { 
     // Query for this interface 
     // 
     Interface* pInterface; 
     hr = p->QueryInterface(GetIID(), reinterpret_cast<void**>(&pInterface)); 

이제 문제는 여기 값이다 "hr"이 반환되면 E_NOINTERFACE ...이 맞지 않습니다.

나는 ...는 C# 측 IScOrder 인터페이스를 구현하지 않는 것 :

답변

1

클래스 ScOrder 도와주세요 어떤 C++ 또는 COM 전문가는 아니지만. 필요 보이지 않는 오히려 때문에, 방해하기 때문에

//[ComVisible(true)] 
//[Guid("F739759E-4D00-440E-B0B7-69AAF97FCB6D")] 
//[ClassInterface(ClassInterfaceType.None)] 
public class ScOrder : IScOrder 

내가하지 위에 [...] 댓글을 달았습니다 :

이 있었어야는 COM의 가시성을 확보하고에 그것을 얻을 수있을 것입니다 IScOrder 필요하다 C++ 쪽.

IScOrder 상속없이 인스턴스에 인터페이스가 있지만 실제로 포인터에 액세스 할 수 없습니다. IScOrder.

+1

다시 말하지만, 나는 StackOverflow에있는 사람들에 의해 눈먼 바보로 판명났습니다. 이 문제를 디버그하여 작동하는지 확인한 다음이를 대답으로 받아 들일 것입니다. – Mirek

+0

어떤 이유로 GetQuantity는 0을 반환하지만 다른 문제입니다. 고마워요 :) – Mirek

+1

'E_NOINTERFACE'는 좋은 힌트입니다.당신은 어떤 물건을 가지고 있으며 그것은 당신의 주문 클래스임을 압니다. 하지만 필요한 인터페이스를 제공하지 않으므로 인터페이스 가시성과 관련된 문제 일뿐입니다. –

관련 문제