E_NOINTERFACE,同时试图获取一个类方法指针 [英] E_NOINTERFACE while trying to get a class method pointer

查看:214
本文介绍了E_NOINTERFACE,同时试图获取一个类方法指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从C ++非托管代码调用C#方法。我有一个从数组中返回的类实例中获取值的问题。



我简化了一些代码



这是有问题的方法。

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

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

这是IScOrder接口

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

这是ScOrder实现

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

public Sc​​Order(){}

public Sc​​Order(long quantity)
{
this.quantity = quantity;
}

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

这是C ++代码,经过Zdeslav的帮助Vojkovic在我的之前的请求




  • 我不使用ATL也不使用MFC。

  • 通过regasm生成C ++ tlb文件。



COM初始化并调用GetOrders方法很好

  IScProxyPtr iPtr; 
CoInitialize(NULL);
iPtr.CreateInstance(CLSID_ScProxy);
SAFEARRAY *订单;
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& lt; elements; i ++)
{
LPUNKNOWN punk = punks [i]; // punk似乎有效
IScOrderPtr order(punk); // unfortunatelly,order现在指向{0x00000000}

//随后尝试获取值将失败
long quantity = 0;
HRESULT procCall;
// GetQuantity将抛出异常
procCall = order-> GetQuantity((long long *)q);

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

感谢Zdeslav,我发现我可以在命令(punk)里面调试:

  IScOrderPtr order(punk); 

所以我踏进了订单(punk)看看发生了什么。我有一个comip.h

  //从任何基于IUnknown的接口指针构造智能指针。 
//
template< typename _InterfaceType> _com_ptr_t(_InterfaceType * p)
:m_pInterface(NULL)
{
HRESULT hr = _QueryInterface(p);

...然后我进入_QueryInterface(p)实现,也在comip.h



  //对pUnknown执行QI,返回的接口类型为
//。接口被存储。如果pUnknown是
// NULL,或者QI失败,则返回E_NOINTERFACE,并将
// _pInterface设置为NULL。
//
template< typename _InterfacePtr> HRESULT _QueryInterface(_InterfacePtr p)throw()
{
HRESULT hr;

//无法QI NULL
//
if(p!= NULL){
//此界面的查询
//
Interface * pInterface;
hr = p-> QueryInterface(GetIID(),reinterpret_cast< void **>(& pInterface));

现在问题是,返回的hr的值是E_NOINTERFACE ...



我没有C ++或COM专家...请帮助:)

解决方案

您的类 ScOrder 似乎没有在C#侧实现 IScOrder 接口。 / p>

应该是:

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

我评论了 [...] 干扰,而不是因为它看起来不必要:它是 IScOrder 需要有COM可见性,应该能够在C ++侧。



无需继承 IScOrder 您的实例确实有一些接口,但是您的兴趣 IScOrder 确实不能在指针上访问。


I'm calling the C# methods from a C++ unmanaged code. I have a problem with getting a value from a class instance returned in array.

I've simplified the code a little bit

This is the problematic method.

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

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

This is the IScOrder interface

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

And this is the ScOrder implementation

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

This is the C++ code, after a help from Zdeslav Vojkovic in my previous request. The problem is described in the comments

  • I'm not using ATL nor MFC.
  • The C++ tlb file is generated via regasm.

COM initialization and calling the GetOrders method works good

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

Thanks to Zdeslav, I discovered that I can debug inside the order(punk):

IScOrderPtr order(punk);

So I stepped into order(punk) to see what's happening there. I got inside a "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);

...then I stepped inside the _QueryInterface(p) implementation, also in 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));

Now the problem here is that the value of "hr" returned is E_NOINTERFACE ... and that's not right.

I'm no C++ or COM expert...please help :)

解决方案

Your class ScOrder does not seem to be implementing IScOrder interface on the C# side.

It should have been:

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

I commented [...] above not because it is interfering, rather because it does not look necessary: it is IScOrder needs to have COM visibility and should be able to get it on C++ side.

Without inheriting IScOrder your instances do have some interface but the one of your interest IScOrder is indeed not accessible on the pointers.

这篇关于E_NOINTERFACE,同时试图获取一个类方法指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆