E_NOINTERFACE尝试获取一个类的方法指针(E_NOINTERFACE while tryi

2019-09-22 11:12发布

我打电话从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<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专家......请帮助:)

Answer 1:

你的类ScOrder似乎并没有被实施IScOrder在C#侧接口。

它应该是:

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

我评论[...]以上,不是因为它的干扰,而是因为它看起来并不需要:这是IScOrder需要有COM的知名度和应该能够得到它在C ++的一面。

没有继承IScOrder您的情况确实有一些接口,但是你的兴趣的一个IScOrder确实不是指针访问。



文章来源: E_NOINTERFACE while trying to get a class method pointer