我从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;
}
}
在我previous request的Zdeslav Vojkovic的帮助下,这是C ++代码。问题在评论中描述
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专家......请帮忙:)。
答案 0 :(得分:1)
您的班级ScOrder
似乎没有在C#端实现IScOrder
接口。
应该是:
//[ComVisible(true)]
//[Guid("F739759E-4D00-440E-B0B7-69AAF97FCB6D")]
//[ClassInterface(ClassInterfaceType.None)]
public class ScOrder : IScOrder
我上面评论[...]
不是因为它干扰,而是因为它看起来不必要:它是IScOrder
需要具有COM可见性并且应该能够在C ++端获得它。
如果没有继承IScOrder
您的实例确实有一些界面,但您的兴趣IScOrder
确实无法在指针上访问。