GUID的COM安全数组';s从C+返回+;到C# 我现在遇到了一个问题,需要把SAFEARE(GUID)作为一个从C++到C的返回值。

GUID的COM安全数组';s从C+返回+;到C# 我现在遇到了一个问题,需要把SAFEARE(GUID)作为一个从C++到C的返回值。,c#,c++,com,guid,safearray,C#,C++,Com,Guid,Safearray,目前,C#端正在使用从Tlbimp.exe(类型库导入器)生成的互操作dll IDL是: HRESULT GetGuids( [out]SAFEARRAY(GUID)* guids); 我也试过了 函数签名为: HRESULT WINAPI MyClass::GetGuids(SAFEARRAY** guids) 如果我使用SafeArrayCreate()或SafeArrayCreateVector(): 我得到一个空的SAFEARRAY指针,它应该指示E_OUTOFMEMORY这

目前,C#端正在使用从Tlbimp.exe(类型库导入器)生成的互操作dll

IDL是:

HRESULT GetGuids(
    [out]SAFEARRAY(GUID)* guids);
我也试过了

函数签名为:

HRESULT
WINAPI
MyClass::GetGuids(SAFEARRAY** guids)
如果我使用
SafeArrayCreate()
SafeArrayCreateVector()

我得到一个空的
SAFEARRAY
指针,它应该指示
E_OUTOFMEMORY
这是不正确的

我发现
VT_CLSID
仅适用于Ole属性集,而不适用于SAFEARRAY的: 它表明CLSID是

我还尝试了构建安全阵列的其他方法,包括:
SafeArrayAllocDescriptor()
SafeArrayAllocData()

这使我可以创建数组,但当使用
SafeArrayPutElement()
填充数组时,我得到的HRESULT为0x80070057(参数不正确)。这可能是因为它也采用了
VT_CLSID
参数

我可以用
SafeArrayAccessData()手动填充它

但我从C#端得到一个错误: “该值不在预期范围内”

我不知道如何通过retval或out参数实现将SAFEARRAY(GUID)返回到C#的预期功能

看起来应该很简单-在IDL中有很多地方我已经在没有任何UDT或编组的情况下传递GUID了。一切正常,直到我需要通过安全阵列

感谢您的帮助,
提前感谢

你说得完全正确-问题是在VARIANT或SAFEARRAY中都不允许使用VT_CLSID。归根结底,GUID不是一种自动化兼容类型


我经常需要做和你一样的事情。解决此问题的最简单方法是将GUID转换为字符串,然后传递SAFEARRAY(VT_BSTR)。进行这种转换在某种程度上违背了原则,但我认为您可以认为,无论如何都会进行封送处理,而且这种转换是封送处理的一种类型。

实现这种转换的方法包括将GUID作为UDT(用户定义类型)传递

为此,我们使用VT_记录元素的SAFEARRAY,这些元素将使用SafeArrayCreateEx进行初始化。但首先,我们必须获得一个指向IRecordInfo的指针,该指针可以描述该类型

由于GUID是在windows/COM标头中定义的,并且没有附加uuid,因此我们必须使用其他方法来获取IRecordInfo接口。基本上,这两个选项是创建一个与您自己的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 );
#不导入名为_guids的名称空间
IRecordInfo*pRecordInfo=NULL;
GetRecordInfoFromGuids(LIBID\u mscorlib、1、0、0、\uu uuidof(Guid)和pRecordInfo);
SafeArrayCreateX(VT_记录,1和sab,预编码信息);

谢谢,所以没有办法做到这一点?我认为这是可能的,因为我已经在使用这种样式:
HRESULT SendGuid([in]GUID)在idl中的许多位置传递单个guid。我真的希望保持界面的纯洁性。要避免只使用字符串,其契约性要高得多:(我同意,我更愿意自己这样做。但是,这是不可能的。原因是ActiveX/Automation是COM的一个子集,旨在使后期绑定的脚本语言能够通过IDispatch轻松与COM对象通信。SAFEARRAY和VARIANT是此自动化子集的一部分,但VT_CLSID不是。您的SendGuid(GUID)方法与自动化不兼容,但它仍然是完美的COM。即使您不希望您的接口与自动化兼容,但只要使用SAFEARRAY类型,您就要付出代价。
hResult = SafeArrayAllocDescriptor(1, guids)
hResult = SafeArrayAllocData(*guids);
GUID* pData = NULL;
hResult = SafeArrayAccessData(*guids, (void**)&pData);
#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 );