更新时间:2021-07-19 23:09:48
与返回数组的问题是,在C ++中,你会看到一个指向struct,没有关于数组大小的信息。你可以尝试元帅它作为一个SAFEARRAY,但IMO,SAFEARRAYS是在颈部疼痛
The problem with returning the array is that in the C++ you will see a pointer to struct and have no information about array size. You can try to marshal it as a SAFEARRAY, but IMO, SAFEARRAYs are pain in the neck.
我喜欢它建模为这样的:
I prefer to model it as this:
[ComVisible(true)]
[Guid("C3E38106-F303-46d9-9EFB-AD8A8CA8644E")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MyStruct
{
public int Value;
// I marshal strings as arrays! see note at the bottom
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Unit
}
[ComVisible(true),
Guid("BD4E6810-8E8C-460c-B771-E266B6F9122F"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IMyService
{
int GetData([MarshalAs(UnmanagedType.LPArray)] out MyStruct[] data);
}
客户端代码是这样的:
The client code is like this:
Lib::MyStruct* data;
long size = svc->GetData(&data);
for(size_t i = 0; i < size; ++i)
{
Lib::MyStruct& current = data[i];
long val = current.Value;
bstr_t unit = current.Unit;
// ...
}
// now you need to release the memory. However, if you marshal
// strings in struct as BSTRs, you need to first release them by
// calling SysFreeString. This is why I prefer to marshal strings
// as arrays whenever I can: you can still easily construct a bstr_t
// in your client code, but you don't need to release them explicitly
CoTaskMemFree(data);
对于有关 SAFEARRAY
评论小号:他们被要求只有当该接口必须是自动化兼容的,即后期绑定,即一个的IDispatch
接口即标记为 ComInterfaceType.InterfaceIsIDispatch
。如果不是这种情况下(我声明即 ComInterfaceType.InterfaceIsIUnknown
界面自定义),使用标准的数组是完全正常的,他们也同样可以支持作为 SAFEARRAY
秒。此外,自定义的结构的 SAFEARRAY
s工作带来一些额外的 复杂性我倾向于避免。如果你不需要后期绑定,没有理由与 SAFEARRAY
秒。
With regard to comment about SAFEARRAY
s: they are required only if the interface must be automation compliant i.e. late-bound i.e. an IDispatch
interface i.e. marked as ComInterfaceType.InterfaceIsIDispatch
. If this is not the case (and I declared the interface as custom i.e. ComInterfaceType.InterfaceIsIUnknown
) using the standard arrays is perfectly fine and they are equally well supported as SAFEARRAY
s. Furthermore, working with SAFEARRAY
s of custom structs brings some additional complexity which I prefer to avoid. If you don't need late binding, there is no reason to fight with SAFEARRAY
s.
打关于 CComSafeArray
,如记录,它不支持 VT_RECORD
这是需要支持的结构阵列(另一种选择是与 IRecordInfo
元帅为 VT_VARIANT
,但我甚至不会去成)。
With regard to CComSafeArray
, as documented, it doesn't support VT_RECORD
which is required to support arrays of structs (another option is to marshal it as VT_VARIANT
with IRecordInfo
but I won't even go into that).