E_NOINTERFACE,同时试图获取一个类方法指针 [英] E_NOINTERFACE while trying to get a class method pointer
问题描述
我从C ++非托管代码调用C#方法。我有一个从数组中返回的类实例中获取值的问题。
我简化了一些代码
这是有问题的方法。
[return:MarshalAs(UnmanagedType.SafeArray,SafeArraySubType = VarEnum.VT_UNKNOWN) ]
public ScOrder [] 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 ScOrder(){}
public ScOrder(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<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屋!