Java-эквиваленты для функций C stdlib - PullRequest
0 голосов
/ 10 сентября 2018

Я не мог придумать лучшего названия, так что вот оно. Я пытаюсь выяснить, каким был бы наилучший (в случае эффективности и чистоты кода) доступ к методам из stdlib of C. Основанием для этого является то, что я пытаюсь получить функциональность mbstowcs в программе Java. Прямо сейчас в моем коде C я получил это:

const char* source = "D:\\test3\\source\\test.txt";
SName tmp1;
mbstowcs((wchar_t*)tmp1, source, 32 - 1);

Где SName равно typedef unsigned short SName[32]. Позже в качестве входного аргумента используется код tmp1:

status = copyFilePath(tmp1, tmp2, info, &context);

Что я по сути пытаюсь сделать, это назвать это copyFilePath со стороны Java с использованием JNA. Хитрость в том, что мне нужно получить аналогичное преобразование для mbstowcs C в Java-программе, чтобы позже я мог напрямую вызывать эту функцию без какой-либо дополнительной обработки. На данный момент мне кажется, что мне понадобится дополнительный код C для использования JNI, чтобы я мог получить оболочку для mbstowcs из stdlib.

Вопрос также заключается в том, есть ли у Java аналогичные способы преобразования многобайтовой строки в строку широких символов, как в C / C ++, чтобы все это работало?

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Не отвечаю на вопрос, но пытаюсь помочь с проблемой. JNA имеет com.sun.jna.WString. Если вы вызываете функцию с параметром WString, она станет широкой строкой в ​​собственном коде. Вам нужно только убедиться, что вы правильно указали кодировку.

Вместо function.invoke(myString);, который дает вам многобайтовую строку на нативной стороне, просто используйте function.invoke(new WString(myString));

0 голосов
/ 10 сентября 2018

Простой естественный способ преобразования байтов в текст - использование строкового конструктора; например,

Charset charset = Charset.forName("UTF-8"); // for example, or use one of
                                            // the predefined Charset constants in
                                            // java.nio.charset.StandardCharsets
byte[] bytes = ...
String text = new String(bytes, charset);

Эффективный способ сделать подобные вещи в Java - это использовать ByteBuffer и CharBuffer объекты и CharsetDecoder заполнять верхнюю из последних.

Но эти подходы не будут работать, если вы используете char* значения с нулевым символом в конце. Стандартные API Java не поддерживают нулевое завершение. (Массив Java имеет четко определенную длину.)

Мой совет - не переводить код напрямую с C / C ++ на Java. Вместо этого пишите это с нуля как идиоматический код Java. (И если вам действительно нужна эффективность кода на C или C ++, используйте эти языки!)

Что я по сути пытаюсь сделать, это вызвать этот copyFilePath со стороны Java с использованием JNA. Хитрость в том, что мне нужно получить аналогичное преобразование для mbstowcs C в Java-программе, чтобы позже я мог напрямую вызывать эту функцию без какой-либо дополнительной обработки.

Итак, простой подход:

  1. Выполните преобразование в то, с чем может справиться Java (например, byte[] или String) на стороне собственного кода.
  2. Передайте byte[] или String или что-либо еще в Java через JNA.
  3. Сделайте так, чтобы сторона Java кэшировала его так, чтобы не нужно было повторять вызов JNA.

Но стоит отметить совет Кнута о преждевременной оптимизации. Если вы так часто пересекаете границу Java / native, что такая оптимизация будет целесообразной, вам следует (IMO) пересмотреть более крупный дизайн вашего приложения; например почему ваша Java так интенсивно вызывает нативный код (или наоборот).

...