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。
  • C ++ tlb文件是通过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); 

感谢Zdeslav,我发现我可以在订单内调试(朋克):

 IScOrderPtr order(punk); 

所以我踏上了订单(朋克),看看那里发生了什么。 我进了一个“comip.h”

 // Constructs a smart-pointer from any IUnknown-based interface pointer. // template _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 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(&pInterface)); 

现在问题是返回的“hr”的值是E_NOINTERFACE ……而且这不对。

我不是C ++或COM专家……请帮忙:)

您的类ScOrder似乎没有在C#端实现IScOrder接口。

应该是:

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

我评论上面的内容不是因为它干扰,而是因为它看起来并不必要:它是IScOrder需要具有COM可见性并且应该能够在C ++端获得它。

如果没有inheritanceIScOrder你的实例确实有一些接口,但你的兴趣IScOrder确实无法在指针上访问。