Java, панама проекта и как работать с результатом «предложения» Hunspell

Я экспериментирую с Hunspell и взаимодействую с ним с помощью Java Project Panama (сборка 19-panama+1-13 (2022/1/18)). Мне удалось провести начальное тестирование, например, при создании и впоследствии использовать это для проверки орфографии. Теперь я пробую что-то более сложное, позволяя Hunspell дать мне слово, которого нет в словаре. Это код, который у меня есть для этого сейчас:

      public class HelloHun {
    public static void main(String[] args) {
        MemoryAddress hunspellHandle = null;
        try (ResourceScope scope = ResourceScope.newConfinedScope()) {
            var allocator = SegmentAllocator.nativeAllocator(scope);

            // Point it to US english dictionary and (so called) affix file
            // Note #1: it is possible to add words to the dictionary if you like
            // Note #2: it is possible to have separate/individual dictionaries and affix files (e.g. per user/doc type)
            var en_US_aff = allocator.allocateUtf8String("/usr/share/hunspell/en_US.aff");
            var en_US_dic = allocator.allocateUtf8String("/usr/share/hunspell/en_US.dic");

            // Get a handle to the Hunspell shared library and load up the dictionary and affix
            hunspellHandle = Hunspell_create(en_US_aff, en_US_dic);

            // Feed it a wrong word
            var javaWord = "koing";

            // Do a simple spell check of the word
            var word = allocator.allocateUtf8String(javaWord);
            var spellingResult = Hunspell_spell(hunspellHandle, word);
            System.out.println(String.format("%s is spelled %s", javaWord, (spellingResult == 0 ? "incorrect" : "correct")));

            // Hunspell also supports giving suggestions for a word - which is what we do next
            // Note #3: by testing this `koing` word in isolation - we know that there are 4 alternatives for this word
            // Note #4: I'm still investigating how to access individual suggestions

            var suggestions = allocator.allocate(10);
            var suggestionCount = Hunspell_suggest(hunspellHandle, suggestions, word);

            System.out.println(String.format("There are %d suggestions for %s", suggestionCount, javaWord));

            // `suggestions` - according to the hunspell API - is a `pointer to an array of strings pointer`
            // we know how many `strings` pointer there are, as that is the returned value from `suggest`
            // Question: how to process `suggestions` to get individual suggestions


        } finally {
            if (hunspellHandle != null) {
                Hunspell_destroy(hunspellHandle);
            }
        }
    }
}

Я вижу, что вызов (созданный из ) завершается успешно и возвращает мне (4) предложения (которые я проверил с помощью Hunspell из командной строки) — так что проблем нет.

Что для меня сейчас более сложно, так это то, как мне распаковать элемент, который возвращается из этого вызова? Я просматривал различные примеры, но ни один из них, похоже, не вдавался в подробности (и даже если я находил примеры, они, похоже, использовали устаревшие API-интерфейсы панамы).

Итак, по сути, вот мой вопрос:

Как распаковать структуру, которая, как сообщается, состоит из указателя на массив строк, указывающих с помощью API Panama JDK19 на соответствующую коллекцию строк?

1 ответ

Глядя на заголовок здесь: https://github.com/hunspell/hunspell/blob/master/src/hunspell/hunspell.h#L80

      /* suggest(suggestions, word) - search suggestions
 * input: pointer to an array of strings pointer and the (bad) word
 *   array of strings pointer (here *slst) may not be initialized
 * output: number of suggestions in string array, and suggestions in
 *   a newly allocated array of strings (*slts will be NULL when number
 *   of suggestion equals 0.)
 */
LIBHUNSPELL_DLL_EXPORTED int Hunspell_suggest(Hunhandle* pHunspell,
                                              char*** slst,
                                              const char* word);

The slstявляется классическим «выходным» параметром. т.е. мы передаем указатель на некоторое значение (в данном случае это массив строк), и функция установит этот указатель для нас, как способ вернуть несколько результатов. (первым результатом является количество предложений)

В панаме вы используете параметры «out», выделяя сегмент с макетом типа, на который параметр является указателем. В таком случае char***является указателем на char**, так что макет ADDRESS. Затем мы передаем созданный сегмент в функцию и, наконец, извлекаем/используем значение из этого сегмента после вызова функции, который заполнит содержимое сегмента:

      // char***
var suggestionsRef = allocator.allocate(ValueLayout.ADDRESS); // allocate space for an address
var suggestionCount = Hunspell_suggest(hunspellHandle, suggestionsRef, word);
// char** (the value set by the function)
MemoryAddress suggestions = suggestionsRef.get(ValueLayout.ADDRESS, 0);

После этого вы можете перебрать массив строк:

      for (int i = 0; i < suggestionCount; i++) {
    // char* (an element in the array)
    MemoryAddress suggestion = suggestions.getAtIndex(ValueLayout.ADDRESS, i);
    // read the string
    String javaSuggestion = suggestion.getUtf8String(suggestion, 0);
}
Другие вопросы по тегам