Вызов функции c из Java - программирование
Подтвердить что ты не робот

Вызов функции c из Java

Как вызвать функцию c из Java. Кажется, c основан на компиляторе.

Я хотел бы вызвать функцию C в Windows с Java, и Функция GCC также доступна для Java.

Любая ссылка?

4b9b3361

Ответ 1

Посмотрите Java Native Interface: Начало работы.

2.1 Обзор

[...] написать простое приложение Java, которое вызывает функцию C для печати "Привет мир!". Процесс состоит из следующих шагов:

Создайте класс (HelloWorld.java), который объявляет собственный метод. использование javac для компиляции исходного файла HelloWorld, в результате чего класс файл HelloWorld.class. Компилятор javac поставляется с JDK или Java 2 выпуска SDK. Используйте javah -jni для создания файла заголовка C (HelloWorld.h), содержащий прототип функции для нативного метода реализация. Инструмент javah снабжен JDK или Java 2 SDK релизы. Напишите реализацию C (HelloWorld.c) родной метод. Скомпилируйте реализацию C в родную библиотеку, создав Hello-World.dll или libHello-World.so. Используйте компилятор C и компоновщик доступный в среде хоста. Запустите программу HelloWorld, используя java runtime interpreter. Оба файла класса (HelloWorld.class) и загружена собственная библиотека (HelloWorld.dll или libHelloWorld.so) во время выполнения. В оставшейся части этой главы объясняются эти шаги в деталь.

2.2 Объявить собственный метод

Вы начинаете с написания следующей программы в Java-программировании язык. Программа определяет класс с именем HelloWorld, который содержит собственный метод, печать.

class HelloWorld {
    private native void print();

    public static void main(String[] args) {
        new HelloWorld().print();
    }

    static {
        System.loadLibrary("HelloWorld");
    }
}

Определение класса HelloWorld начинается с объявления собственного метода печати. За этим следует основной метод, который создает экземпляр класса Hello-World и вызывает собственный метод печати для этого экземпляра. Последняя часть определения класса является статической инициализатор, который загружает собственную библиотеку, содержащую реализация собственного метода печати. ​​

Существуют две отличия между объявлением нативного метода таких как печать и объявление регулярных методов в Java язык программирования. Объявление нативного метода должно содержать собственный модификатор. Модификатор native указывает, что этот метод реализован на другом языке. Кроме того, декларация нативного метода заканчивается точкой с запятой, символом терминатора оператора, потому что в классе нет реализации для собственных методов сам. Мы будем применять метод печати в отдельном файле C.

Прежде чем можно вызвать печать нативного метода, встроенная библиотека, которая реализует печать. В этом случае мы загружаем библиотеки в статическом инициализаторе класса HelloWorld. Java виртуальная машина автоматически запускает статический инициализатор до вызывая любые методы в классе HelloWorld, гарантируя тем самым, что загружается исходная библиотека до того, как вызывается собственный метод печати. ​​

Мы определяем основной метод, чтобы иметь возможность запускать класс HelloWorld. Hello-World.main вызывает собственный метод печати таким же образом, как и он будет вызывать обычный метод.

System.loadLibrary принимает имя библиотеки, находит собственную библиотеку, которая соответствует этому имени и загружает собственную библиотеку в выражение. Мы обсудим процесс точной загрузки позже в книга. Пока просто помните, что для System.loadLibrary("HelloWorld") для успеха, нам нужно создать родную библиотеку под названием HelloWorld.dll на Win32, или libHelloWorld.so on Solaris.

2.3 Скомпилируйте класс HelloWorld

После того, как вы определили класс HelloWorld, сохраните исходный код в файл HelloWorld.java. Затем скомпилируйте исходный файл, используя javac, который поставляется с версией JDK или Java 2 SDK:

 javac HelloWorld.java

Эта команда будет генерировать HelloWorld.classфайл в текущем каталоге.

2.4 Создайте файл заголовка исходного кода

Далее мы будем использовать инструмент javah для создания заголовочного файла в стиле JNI это полезно при реализации собственного метода в C. Вы можете запускать javah в классе Hello-World следующим образом:

  javah -jni HelloWorld

Имя файла заголовка - это имя класса с добавлением ".h" к концу. Команда, показанная выше генерирует файл с именем HelloWorld.h. Мы не будем перечислять сгенерированные файл заголовка целиком. Важнейшая часть заголовочный файл является прототипом функции для Java_HelloWorld_print, который является функцией C, реализующей метод HelloWorld.print:

 JNIEXPORT void JNICALL   Java_HelloWorld_print (JNIEnv *, jobject);

Игнорировать макросы JNIEXPORT и JNICALL. Возможно, вы заметили что реализация C нативного метода принимает два аргумента даже если соответствующая декларация родного метода принимает нет аргументов. Первый аргумент для каждого нативного метода реализация - это указатель интерфейса JNIEnv. Второй аргумент - ссылку на сам объект HelloWorld (вроде как "this" указатель в С++). Мы обсудим, как использовать интерфейс JNIEnvуказатель и аргументы jobject в этой книге, но этот простой пример игнорирует оба аргумента.

2.5 Запишите исходный метод реализации

Заголовочный файл в стиле JNI, сгенерированный javah, позволяет вам писать C или С++ для собственного метода. Функция, которую вы пишете должен следовать -prototype, указанному в сгенерированном файле заголовка. Вы может реализовать метод Hello-World.print в файле C HelloWorld.c как следующим образом:

#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"   

JNIEXPORT void JNICALL   Java_HelloWorld_print(JNIEnv *env, jobject obj)  {
     printf("Hello World!\n");
     return;
}

Реализация этого нативного метода проста. Он использует функцию printf для отображения строки "Hello World!". а затем возвращается. Как упоминалось ранее, оба аргумента, указатель JNIEnv и ссылка на объект игнорируются.

Программа C включает в себя три файла заголовка:

jni.h - Этот заголовочный файл предоставляет информацию, необходимую для внутреннего кода для вызова функций JNI. При написании собственных методов вы всегда должны включить этот файл в исходные файлы C или С++. stdio.h - код фрагмент выше также включает stdio.h, поскольку он использует printfфункция. HelloWorld.h - файл заголовка, который вы создали с помощью javah. Он включает прототип C/С++ для Java_HelloWorld_printфункция. 2.6. Скомпилировать источник C и создать собственную библиотеку.

Помните, что когда вы создали класс HelloWorld в HelloWorld.java, вы включили строку кода, которая загружала родной библиотеки в программу:

 System.loadLibrary("HelloWorld");   

Теперь, когда весь необходимый код C написано, вам нужно скомпилировать Hello-World.c и построить этот родной библиотека.

Различные операционные системы поддерживают разные способы создания собственных библиотеки. В Solaris следующая команда создает общую библиотеку называется libHello-World.so:

 cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so

Опция -G указывает компилятору C генерировать общую библиотеку вместо обычной Solaris запускаемый файл. Из-за ограничения ширины страницы в этой книге, мы разбиваем командную строку на две строки. Вам нужно ввести команду в одной строке или поместить команду в файл script. На Win32следующая команда создает динамическую библиотеку ссылок (DLL) HelloWorld.dllиспользуя компилятор Microsoft Visual С++:

 cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll 

Параметр -MD гарантирует, что HelloWorld.dll связан с многопоточной библиотекой C Win32. Параметр -LD указывает компилятору C генерировать DLL вместо обычный исполняемый файл Win32. Конечно, на Solaris и Win32 вы необходимо включить включенные пути, которые отражают настройку самостоятельно машина.

2.7 Запустите программу

На этом этапе у вас есть два компонента, готовые для запуска программы. Файл класса (HelloWorld.class) вызывает собственный метод, а native library (Hello-World.dll) реализует собственный метод.

Поскольку класс HelloWorld содержит свой собственный основной метод, вы можете запускать программы на Solaris или Win32 следующим образом:

 java HelloWorld

Вы должны увидеть следующий вывод:

   Hello World! 

Важно установить свой путь к исходной библиотеке правильно для вашей программы. Коренной путь библиотеки - это список каталогов, которые виртуальная машина Java ищет при загрузке родные библиотеки. Если у вас нет пути к исходной библиотеке правильно, тогда вы увидите ошибку, аналогичную следующей:

 java.lang.UnsatisfiedLinkError: no HelloWorld in library path
         at java.lang.Runtime.loadLibrary(Runtime.java)
         at java.lang.System.loadLibrary(System.java)
         at HelloWorld.main(HelloWorld.java) 

Убедитесь, что родная библиотека находится в одном из каталогов в корневом пути библиотеки. Если вы работаете в системе Solaris, LD_LIBRARY_PATHпеременная среды используется для определения пути собственной библиотеки. Делать убедитесь, что он содержит имя каталога, содержащего libHelloWorld.so. Если файл libHelloWorld.so находится в текущем каталога, вы можете выпустить следующие две команды в стандарте shell (sh) или KornShell (ksh) для настройки LD_LIBRARY_PATHпеременная среды:

 LD_LIBRARY_PATH=.
 export LD_LIBRARY_PATH

Эквивалентная команда в оболочка C (csh или tcsh) выглядит следующим образом:

 setenv LD_LIBRARY_PATH .

Если вы работаете в Windows 95 или Windows NT, убедитесь, что HelloWorld.dll находится в текущей каталога или в каталоге, указанном в среде PATH переменная.

В версии Java 2 SDK 1.2 вы также можете указать собственную библиотеку путь в командной строке java как системное свойство следующим образом:

 java -Djava.library.path=. HelloWorld

Параметр командной строки "-D" устанавливает свойство системы платформы Java. Установка java.library.pathСвойство "." указывает виртуальной машине Java на поиск родные библиотеки в текущем каталоге.

Ответ 2

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

Я бы рекомендовал против raw JNI, так как он содержит много кода шаблона, и вы закончите проклинать себя, если начнете обертывать большую библиотеку C. Во всяком случае, не стесняйтесь играть в JNI, когда начинаете, но используйте что-то вроде JNA, когда дело доходит до реальной работы.

Ответ 3

У вас есть варианты:

Явный интерфейс Java
см. https://en.wikipedia.org/wiki/Java_Native_Interface

цитата:

JNI позволяет программистам писать собственные методы для обработки ситуаций, когда приложение не может быть полностью написано на языке программирования Java, например. когда стандартная библиотека классов Java не поддерживает специфичные для платформы функции или библиотеку программ

Явный доступ к Java

см. https://en.wikipedia.org/wiki/Java_Native_Access

цитата:

Java Native Access - это разработанная сообществом библиотека, которая предоставляет программам Java простой доступ к родным общим библиотекам без использования интерфейса Java Native.

JNR-FFI

см.: https://github.com/jnr/jnr-ffi

цитата:

jnr-ffi - это java-библиотека для загрузки собственных библиотек без написания кода JNI вручную или с помощью таких инструментов, как SWIG.

Ответ 4

В категории "экзотические" см. NestedVM, который компилирует C в Mips и запускает Mips VM внутри JVM.

http://nestedvm.ibex.org/

Ответ 5

Если вы используете Windows и MinGW gcc, вам может понадобиться дополнительный флаг, если вы получаете UnsatisfiedLinkError для определенного метода в lib:

gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"%JAVA_HOME%"\include -I"%JAVA_HOME%"\include\win32 BestCode.c -shared -o BestCode.dll

Ответ 6

JNI - Java Native Interface

Чтобы вызвать функцию C из Java, вам нужно использовать JNI

Ответ 7

Оформить заказ JNAerator. https://code.google.com/p/jnaerator/

Вам необходимо указать определения исходного кода и препроцессора и т.д.

Ответ 8

Для создания 64-разрядной совместимой dll. Удалите параметр -MD из инструкции ниже

"cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll"

Ответ 9

У меня есть решение этой проблемы. Что вам нужно, это компиляция кода с использованием 64-разрядного компилятора С++ для вызова функции java, работающей на 64-битной JRE. Наряду с этим нам нужно сохранить путь созданного файла dll в "Путь" в разделе "Переменная среды".

Ответ 10

Сначала убедитесь, что вы загрузите свою родную библиотеку или DLL файл в путь класса, установив путь в свойстве java.library.path

Затем используйте System.loadLibrary()

Do not use .dll extension at the end.