【问题标题】:Marshalling VARIANT across ABI boundaries in a WinRT component在 WinRT 组件中跨 ABI 边界编组 VARIANT
【发布时间】:2012-08-13 14:43:52
【问题描述】:

我正在移植我们的组件,该组件的核心是用 C++ 编写的,同时具有 ActiveX 和 .Net shell。组件内部在很多地方都使用了 VARIANT 类型。该组件参数的一些公共属性(get/set)和方法在 ActiveX 实现中属于 VARIANT 类型,在 .Net 实现中属于 System::Object 类型。在我们的代码内部,我们直接使用 VARIANT。

在实现 ActiveX 组件时,我不需要执行任何封送处理,因为 VARIANT 是 OLE/COM 类型。

在实现.Net组件的时候,我用的类似这样:

VARIANT var;

//...

//Initialize the VARIANT value

//...


System::IntPtr p( &var );

System::Object ^o = System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant(p );

return o;

在 WinRT 中,似乎没有任何类似的 Marshal 类可以完成这项工作。根据 MSDN,“WinRT Platform::Runtime::InteropServices 命名空间仅供内部使用,不用于开发。”

我有哪些选择?当然,必须有一个现有的类来完成跨 ABI 边界编组 VARIANT 的工作。我不想写这样的编组器然后发现它已经存在了!

任何帮助将不胜感激。

【问题讨论】:

标签: c++ windows-runtime variant


【解决方案1】:

感谢您的回复。我最终使用 Windows::Foundation::IPropertyValue 编写了一个实用程序类。

我在此处发布了代码以及返回此主题的链接:

Marshalling a VARIANT in a WinRT component

例子:

// in a C# we can write:
string [] sarray = new string[2];
sarray[0] = "abc";
sarray[1] = "def";

SetValue(sarray);

//in C++/CX we write:
void SetValue( Object ^value )
{
    VARIANT var;
    VariantInit( &var );

    var = acMarshall::MarshalObjectToVariant( value );
    //
    // We will have a SAFEARRAY of BSTRs in the VARIANT...
    //
    VariantClear( &var );
}

// and the reverse, in C++/CX
Object ^ GetValue()
{
    VARIANT var;
    VariantInit(&var);

    v.vt = VT_BSTR | VT_ARRAY;

    SAFEARRAYBOUND sab;
    sab.cElements = 2;
    sab.lLbound = 0;
    SAFEARRAY *psa = SafeArrayCreate( VT_BSTR, 1, &sab );
    LPVOID p = NULL;
    SafeArrayAccessData( psa, &p );

    ((BSTR *) p)[0] = SysAllocString(L"string one");
    ((BSTR *) p)[1] = SysAllocString(L"string two");

    SafeArrayUnaccessData( psa );
    var.parray = psa;

    Object ^ obj = acMarshall::MarshalVariantToObject( var );
    VariantClear( &var );

    return obj;
}

//and in C#:
object obj = GetValue() //obj will contain a string array...

问候,

罗杰

【讨论】:

    【解决方案2】:

    Windows 运行时中没有等效的“VARIANT”。在 ABI 级别,System::Object 表示为实现 IInspectable 的对象,这可能是一种可以用来替换变体的机制。

    可以使用 IReference 创建一个基于 IInspectable 的接口,该接口代表您的更高级别的对象,但它不会像 VARIANT 那样具有弱类型语义。

    【讨论】:

    • 不确定“不会像 VARIANT 那样具有弱类型语义”是什么意思。我能够使用IPropertyValueget_Type 方法来实现这一点。 (类似于@Roger 的回答。)我会说,从 C 程序员的角度来看,VARIANT 更容易使用,内存开销比IPropertyValue 少,而且没有那些不必要的虚拟调用。
    • VARIANT 是弱类型的 - 您可以将 int 放入变量中并取出字符串(反之亦然或任何其他类型的转换 - 请参阅 VariantChangeType 函数)。 IPropertyValue 是强类型的——你只能取出你输入的属性类型。
    猜你喜欢
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    相关资源
    最近更新 更多