E_NOINTERFACE при попытке получить указатель на метод класса

Я вызываю методы C # из неуправляемого кода C ++. У меня проблема с получением значения из экземпляра класса, возвращенного в массиве.

Я немного упростил код

Это проблемный метод.

    [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();
}

И это реализация 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 ++, после помощи от Zdeslav Vojkovic в моем предыдущий запрос. Проблема описана в комментариях

  • Я не использую ни ATL, ни MFC.
  • Файл T ++ C ++ генерируется с помощью regasm.

Инициализация COM и вызов метода GetOrders работают хорошо

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);

…затем я вошел в реализацию _QueryInterface (p), также в comip.h

// 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 ++ или COM эксперт … пожалуйста, помогите 🙂

3

Решение

Твой класс ScOrder не похоже на реализацию IScOrder интерфейс на стороне C #.

Это должно было быть:

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

Я прокомментировал [...] выше не потому, что это мешает, а потому, что это не выглядит необходимым: это IScOrder должен иметь видимость COM и должен иметь возможность получить его на стороне C ++.

Без наследования IScOrder ваши экземпляры имеют некоторый интерфейс, но тот, который вас интересует IScOrder действительно не доступен по указателям.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]