简体   繁体   English

GUID的COM SAFEARRAY从C ++返回到C#

[英]COM SAFEARRAY of GUID's returned from C++ to C#

I'm currently running into an issue of needing to pass a SAFEARRAY(GUID) as a return value from C++ to C#. 我目前遇到一个问题,需要将SAFEARRAY(GUID)作为返回值从C ++传递给C#。

Currently the C# side is using an Interop dll generated from Tlbimp.exe (Type Library Importer). 目前,C#端正在使用从Tlbimp.exe(类型库导入程序)生成的Interop dll。

The IDL is: IDL是:

HRESULT GetGuids(
    [out]SAFEARRAY(GUID)* guids);

I've also tried [out, retval] 我也试过[out,retval]

The function signature is: 功能签名是:

HRESULT
WINAPI
MyClass::GetGuids(SAFEARRAY** guids)

If I use SafeArrayCreate() or SafeArrayCreateVector() : 如果我使用SafeArrayCreate()SafeArrayCreateVector()

SAFEARRAY* psa
psa = SafeArrayCreate(VT_CLSID, 1, rgsabound);

I get a NULL SAFEARRAY pointer, which is supposed to indicate E_OUTOFMEMORY which is incorrect. 我得到一个NULL SAFEARRAY指针,它应该指示E_OUTOFMEMORY不正确。

What I did find was that VT_CLSID is only for Ole property sets and not SAFEARRAY's: http://poi.apache.org/apidocs/org/apache/poi/hpsf/Variant.html Its indicated that CLSID is 我找到的是VT_CLSID仅用于Ole属性集而不是SAFEARRAY: httpVT_CLSID它表明CLSID是

I've also tried the alternate means of constructing the safe array with: SafeArrayAllocDescriptor() and SafeArrayAllocData() . 我还尝试了使用SafeArrayAllocDescriptor()SafeArrayAllocData()构建安全数组的替代方法。

hResult = SafeArrayAllocDescriptor(1, guids)
hResult = SafeArrayAllocData(*guids);

This lets me create the array, but when populating it with SafeArrayPutElement() I get an HRESULT of 0x80070057 (The parameter is incorrect). 这让我创建了数组,但是当用SafeArrayPutElement()填充它时,我得到一个0x80070057的HRESULT(参数不正确)。 This is probably due to the fact it takes the VT_CLSID parameter as well 这可能是因为它也需要VT_CLSID参数

I can populate it manually with SafeArrayAccessData() 我可以使用SafeArrayAccessData()手动填充它

GUID* pData = NULL;
hResult = SafeArrayAccessData(*guids, (void**)&pData);

but I get an error from the C# side: "The value does not fall within the expected Range" 但我从C#端得到一个错误:“该值不在预期的范围内”

I'm not sure how to accomplish the desired functionality of returning a SAFEARRAY(GUID) to C# either by a retval or out parameter. 我不确定如何通过retval或out参数完成将SAFEARRAY(GUID)返回到C#的所需功能。

It seems it should be simple - there are many areas in the IDL where I'm already passing GUID's without any UDT's or marshalling. 它似乎应该很简单 - IDL中有很多区域我已经在没有任何UDT或编组的情况下传递GUID。 Everything works fine until I need to pass them in a SAFEARRAY. 一切正常,直到我需要在SAFEARRAY传递它们。

Any help is appreciated, Thanks in advance 任何帮助表示赞赏,在此先感谢

You're absolutely right - the problem is that VT_CLSID isn't allowed in either VARIANT or SAFEARRAY. 你是绝对正确的 - 问题是VARIANT或SAFEARRAY中不允许使用VT_CLSID。 It boils down to GUID not being an Automation-compatible type. 归结为GUID不是自动化兼容类型。

I often need to do the same thing that you're trying. 我经常需要做你正在尝试的同样的事情。 The easiest way around the problem is to convert the GUID to a string and then pass SAFEARRAY(VT_BSTR). 解决此问题的最简单方法是将GUID转换为字符串,然后传递SAFEARRAY(VT_BSTR)。 It goes against the grain somewhat to do this conversion, but I suppose you could take the view that there's marshaling going on anyway and this conversion is a type of marshaling. 这种转换在某种程度上与谷物相反,但我认为你可以认为无论如何都会进行编组,这种转换是一种编组。

The way to do it involves passing GUIDs as a UDT (user defined type). 执行此操作的方法涉及将GUID作为UDT(用户定义的类型)传递。

For that, we use a SAFEARRAY of VT_RECORD elements which will be initialized with SafeArrayCreateEx. 为此,我们使用了一个VT_RECORD元素的SAFEARRAY,它将使用SafeArrayCreateEx进行初始化。 But first, we have to get a pointer to IRecordInfo that can describe the type. 但首先,我们必须得到一个指向IRecordInfo的指针,它可以描述该类型。

Since GUID is defined in the windows/COM headers and has no uuid attached to it, we have to use something else to get an IRecordInfo interface. 由于GUID是在windows / COM头中定义的,并且没有附加uuid,因此我们必须使用其他东西来获取IRecordInfo接口。 Basically, the two options are to create a struct that has the same memory layout as GUID in your own TypeLib, or use mscorlib::Guid defined in mscorlib.tlb 基本上,这两个选项是在您自己的TypeLib中创建一个与GUID具有相同内存布局的结构,或者使用mscorlib.tlb中定义的mscorlib :: Guid

#import <mscorlib.tlb> no_namespace named_guids

IRecordInfo* pRecordInfo = NULL;
GetRecordInfoFromGuids( LIBID_mscorlib, 1, 0, 0, __uuidof(Guid), &pRecordInfo );

SafeArrayCreateEx( VT_RECORD, 1, &sab, pRecordInfo );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM