Как вызвать функцию c из Java. Кажется, c основан на компиляторе.
Я хотел бы вызвать функцию C в Windows с Java, и Функция GCC также доступна для Java.
Любая ссылка?
Как вызвать функцию c из Java. Кажется, c основан на компиляторе.
Я хотел бы вызвать функцию C в Windows с Java, и Функция GCC также доступна для Java.
Любая ссылка?
Посмотрите 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
в файле CHelloWorld.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
связан с многопоточной библиотекой CWin32
. Параметр-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 на поиск родные библиотеки в текущем каталоге.
Проще говоря, просто загрузите соответствующую библиотеку, которая содержит определение функции, загрузите библиотеку, которая следует спецификации JNI, и обертывает целевую функцию из первой библиотеки, выставляйте собственные методы из вашего Java-класса, и вы должны быть хорошо идти.
Я бы рекомендовал против raw JNI, так как он содержит много кода шаблона, и вы закончите проклинать себя, если начнете обертывать большую библиотеку C. Во всяком случае, не стесняйтесь играть в JNI, когда начинаете, но используйте что-то вроде JNA, когда дело доходит до реальной работы.
У вас есть варианты:
Явный интерфейс 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.
В категории "экзотические" см. NestedVM, который компилирует C в Mips и запускает Mips VM внутри JVM.
Если вы используете 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
JNI - Java Native Interface
Чтобы вызвать функцию C из Java, вам нужно использовать JNI
Оформить заказ JNAerator. https://code.google.com/p/jnaerator/
Вам необходимо указать определения исходного кода и препроцессора и т.д.
Для создания 64-разрядной совместимой dll. Удалите параметр -MD из инструкции ниже
"cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll"
У меня есть решение этой проблемы. Что вам нужно, это компиляция кода с использованием 64-разрядного компилятора С++ для вызова функции java, работающей на 64-битной JRE. Наряду с этим нам нужно сохранить путь созданного файла dll в "Путь" в разделе "Переменная среды".
Сначала убедитесь, что вы загрузите свою родную библиотеку или DLL файл в путь класса, установив путь в свойстве java.library.path
Затем используйте System.loadLibrary()
Do not use .dll extension at the end.