6

我有一个带有以下声明(接口和实现)的托管函数:

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
String[] ManagedFunction()
{
    String[] foo = new String[1];
    foo[0] = "bar";
    return foo;
}

还有一个本地 C++ 接口,其方法与托管接口相同,在该接口内部,此方法具有以下声明:

void ManagedFunction(SAFEARRAY* foo); 

本机代码通过以下方式调用此函数:

void NativeFunction(ManagedBinding binding)
{
    CComSafeArray<BSTR> cComSafeArray;
    cComSafeArray.Create(); 
    LPSAFEARRAY safeArray = cComSafeArray.Detach();
    binding.comObject->ManagedFunction(safeArray); 
}

我不确定我做错了什么,但是在调用我的托管函数之后,safeArray似乎有垃圾值,在将返回值编组回本机代码时出现了问题。在.Net interop 方面比我更有经验的人可以对此有所了解吗?ValueType此外,可能值得一提的是,我从托管函数返回 s 没有问题(boolean如果你好奇的话),关于返回String数组的一些事情会搞砸。谢谢!

4

2 回答 2

0

1)您的函数返回 a SAFEARRAY,那么为什么在调用函数之前分配它?
2)ManagedFunction应该返回 a SAFEARRAY,所以它应该得到 aSAFEARRAY*才能返回它!所以你应该说:

LPSAFEARRAY lpsa;
binding.comObject->ManagedFunction(&lpsa);
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Attach(lpsa);
于 2012-12-01T00:03:29.373 回答
0

好吧,我终于让它工作了。我创建了一个SAFEARRAY被调用的托管表示ManagedSafeArray(从这里窃取:http ://social.msdn.microsoft.com/Forums/en-US/clr/thread/6641abfc-3a9c-4976-a523-43890b2b79a2/ ):

[StructLayout(LayoutKind.Sequential)]
struct ManagedSafeArray
{
    public ushort   dimensions;     // Count of dimensions in the SAFEARRAY
    public ushort   features;       // Flags to describe SAFEARRAY usage
    public uint     elementSize;    // Size of an array element
    public uint     locks;          // Number of times locked without unlocking
    public IntPtr   dataPtr;        // Pointer to the array data
    public uint     elementCount;   // Element count for first (only) dimension
    public int      lowerBound;     // Lower bound for first (only) dimension
}

我将方法的签名更改为:

void ManagedMethod(ref ManagedSafeArray foo);

在我的方法中,我dataPtr通过调用手动更新了字段Marshal.AllocCoTaskMem(...),然后复制了我想要SAFEARRAY包含的字符串。

我不知道为什么 CLR 无法自动将参数编组到本机代码和从本机代码编组,如果有人可以尝试解释这一点,我仍然会很感激。

于 2012-12-03T18:32:54.163 回答