如何从非托管接口方法正确返回值?

时间:2010-12-14 05:50:10

标签: c# pinvoke marshalling xulrunner geckofx

我正在扩展GeckoFx(http://geckofx.org),并且在从XPCom提供的非托管接口返回数组值时遇到一些问题。

我使用最新的XulRunner 1.9.2.13版本为GeckoFx添加了大量新功能支持但是,当尝试从接口方法返回数组时,我遇到了访问冲突异常。 例如:

[Guid("43987F7B-0FAA-4019-811E-42BECAC73FC5"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface mozISpellCheckingEngine
{
    //...
    void GetDictionaryList([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)]ref string[] dictionaries, out uint count);
    //...
}

public static string[] GetAvailableDictionaries()
{
    string[] _dictionaries = null;
    uint count = 0;

    //GetSpellChecker() returns a valid mozISpellCheckingEngine object
    GetSpellChecker().GetDictionaryList(ref _dictionaries, out count);
    if (count > 0)
    {
        if (_dictionaries != null)
        {
            return _dictionaries;
        }
    }
    return null;
}

问题是当GetDictionaryList有时返回时,它会返回一个带有单个索引并包含一个字典名称的列表(我在该方法搜索的位置有2个字典),count返回正确值为2;其他时候该方法将失败并抛出访问冲突,_dictionaries的值为字符串[0],而计数保持正确,值为2.

我想这个问题的最大部分必须是'我是否在接口声明中正确编组方法及其参数?'。

这个示例代码只是一个例子。我想在GeckoFx中实现其他几个XulRunner功能,但是它们也会返回数组并遇到同样的问题。直到我能够解决这个问题,我的工作才有点停滞不前。

感谢您提供的任何和所有帮助。

-Scott

1 个答案:

答案 0 :(得分:0)

变化:

void GetDictionaryList([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)]ref string[] dictionaries, out uint count);

为:

void GetDictionaryList(ref IntPtr dictionaries, out uint count); 

并使用它:

IntPtr dictionaries = IntPtr.Zero;
int count;

GetDictionaryList(ref dictionaries, count);

 // check dictionaries != IntPtr.Zero; and count > 0

 // dictionaries will be a IntPtr to array IntPtr (of size count)

 string vals = new string[count];

 for(int i = 0; i < count; ++i)
  vals[i] = Marshal.PtrToStringUni(Marshal.SizeOf(typeof(IntPtr)) * i);

(我没有编译此代码,因此可能存在拼写错误。)