2010-12-14 3 views
0

Я продолжаю расширять GeckoFx (http://geckofx.org), и у меня возникают проблемы с возвратом значений массива из неуправляемых интерфейсов, предоставляемых XPCom.Как правильно вернуть значения из метода неуправляемого интерфейса?

Я добавил большое количество новых функций поддержки GeckoFx, используя новейшую сборку XulRunner 1.9.2.13, но я получаю исключения при нарушении прав доступа при попытке вернуть массивы из методов интерфейса. Например:

[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 словаря в том месте, этот метод поиск в) и сосчитать возвращается с правильное значение 2; в противном случае метод будет терпеть неудачу и бросить нарушение прав доступа, а значение словаря - строка [0], в то время как счетчик остается правильным со значением 2.

Я предполагаю, что большая часть этого вопроса должна быть «Я упорядочивание метода и его параметров в объявлении интерфейса? '.

Этот пример кода - это просто пример. Есть несколько других функций XulRunner, которые я хотел бы реализовать в GeckoFx, но они также возвращают массивы и страдают от одной и той же проблемы. Пока я не смогу преодолеть эту проблему, моя работа немного стоит на месте.

Спасибо за любую помощь, которую вы можете предоставить.

-Скотт

+0

Попробуйте отбросить ключевое слово 'ref' из аргумента массива, поскольку это подразумевает указатель на указатель на данные (массивы неявно указывают на C#), и я предполагаю, что интерфейс указывает указатель на данные (как является общим для массивов C). – cdhowie

+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); 

(я не компилируется этот код, так что могут быть опечатки.)

+0

На самом деле, я ответил на вопрос несколько раз после публикации его. Ответ, приведенный выше, довольно близок к тому, что у меня получилось. – Scott