Страницы

Поиск по вопросам

Показаны сообщения с ярлыком jni. Показать все сообщения
Показаны сообщения с ярлыком jni. Показать все сообщения

суббота, 8 февраля 2020 г.

Java вызов WinApi функций или управление открытыми окнами чужих программ

#java #winapi #jni


Здравствуйте!

Есть программа написанная на JAVA(модуль запускаемый как надстройка одновременно
со сторонним приложением). 

Из этой java-программы (надстройки), необходимо менять заголовок окон сторонней программы.  

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

Без проблем могу решить данную задачу на С++ или на Delphi. 

Но задача состоит в том, чтобы сделать изменение заголовка чужой программы средствами
JAVA.

Начальство очень  не хочет плодить в проекте  модули написанные не полностью на java
(если никак по-другому - смирятся).

Рассматриваю варианты по отлову handle, заголовков окна, по id-процесса, по классу
окна...  Боже! да как угодно -главное чтобы работало!

С радостью приму от вас советы, ссылки, комментарии, и кусочки кода.

Было бы отлично, если кто-то поделится исходником подобной задачи.

Примеры с JNA ,  JNI  приму с радостью!  
    


Ответы

Ответ 1



Конечно, JNA — это ваш выбор. Надо скачать две JAR-ки здесь, либо подключить через maven. Вот набросал пример: import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIOptions; public class SetWindowTitle { public static interface User32 extends StdCallLibrary { final User32 instance = (User32) Native.loadLibrary ("user32", User32.class, W32APIOptions.UNICODE_OPTIONS); HWND FindWindow(String className, String windowName); boolean SetWindowText(HWND hwnd, String newText); } public static void main(String[] args) { if(args.length != 2) { System.out.println("Нужно два аргумента: имя окна (или класс) и новое имя"); return; } HWND hwnd = User32.instance.FindWindow(args[0], null); if(hwnd == null) { hwnd = User32.instance.FindWindow(null, args[0]); } if(hwnd == null) { System.out.println("Окно не найдено"); return; } System.out.println("Нашли окно: "+hwnd); boolean result = User32.instance.SetWindowText(hwnd, args[1]); System.out.println(result ? "Успешно" : "Упс"); } } Компилировать: javac -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle.java Запускать java -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle "old-title" "new-title" JNA очень удобно работает. Вы просто объявляете в вашем интерфейсе методы с теми же именами, что в user32 и с совместимой сигнатурой. Внутри JNA создаёт Proxy-класс, который для каждого метода поищет соответствующий внутри user32.dll и преобразует нужным образом аргументы.

воскресенье, 26 января 2020 г.

Android NDK: возврат массива

#android_sdk #jni #cpp


В программе на с++ формируются данные, которые требуется передать в java. Данные
в виде нескольких объектов class{ String name; int x, y, sx, sy; }; Можно запрашивать
каждое значение отдельной функцией, но это совсем не вариант.
Есть способ, которым можно вернуть в java массив, например в виде списка ключей и
значений? Или в виде дерева, куда можно положить сразу все необходимые значения. То
есть вопрос: как вернуть значения и пользоваться ими с легкостью и простотой.
UPD. Вот как-то так. http://mikelsv.livejournal.com/8902.html . << Это ответ.    


Ответы

Ответ 1



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

четверг, 23 января 2020 г.

Реализация native методов

#java #cpp #winapi #jni


Нужно с помощью JNI из Java реализовать работу с фунциями Win32 API:
VirtualAlloc, VirtualFree, VirtualLock, VirtualUnlock. Создал .h файл с помощью javah,
но не знаю как реализовать эти методы. Нигде не могу найти пример.
    


Ответы

Ответ 1



Создай java класс например WinWork. И в нём объяви нужные функции(Например VirtualAlloc, VirtualFree) и напиши загрузку либы: package my.pack; public class WinWork { static { System.loadLibrary("libname"); } native public static void virtualAlloc(); native public static void virtualFree(); } теперь при вызове WinWork.virtualAlloc() JVM будет искать в либах метод Java_my_pack_WinWork_virtualAlloc(...) Далее нужно объявить JNI функций в C++. Нам надо создать хедеры с объявлениями функций C++, которые мы хотим вызывать. Можно написать их вручную или заюзать: javac -d bin/ src/my/pack/WinWork.java cd bin javah my.pack.WinWork Появится примерно такой хейдер(или можно написать его вручную): #include JNIEXPORT void JNICALL Java_my_pack_WinWork_virtualAlloc(JNIEnv *, jclass); JNIEnv — это интерфейс к виртуальной машине. Все операции с JVM выполняются с помощью него. jclass — это идентификатор java класса, у которого есть метод native, отождествленный с этой функцией, то есть в нашем случае это WinWork. Но jclass в качестве второго параметра передается тогда, когда метод объявлен как static. Если бы он был обычным методом, то нам бы передавался jobject, который бы идентифицировал объект, метод которого мы вызвали (фактически это аналог this). Остается только реализовать эти функции.

среда, 22 января 2020 г.

JNI код падает в core dump когда в коде вызывается throw на 64 bit SunOs

#java #cpp #jni #solaris


bash-3.00$ uname -a
SunOS x2001 5.10 Generic_142910-17 i86pc i386 i86pc 

bash-3.00$ gcc --version
gcc (GCC) 4.4.2 Copyright (C) 2009 Free Software Foundation, Inc. This is free software;
see the source for copying conditions. 


Написан код на Java и c++ (с использованием JNI). Но когда вызывается исключение,
обработка не попадает в свой catch-обработчик, а вызывается сразу системный и приложение
падает в корку.

Однако тот же самый код прекрасно работает на Linux 64bit, SPARC 64bit и i386 32bit.
Проблема возникает при попытке запуска под Java 8 (по дефолту только 64 бита поддерживается)
на Intel SunOs.

Флаг -m64 был добавлен в Makefile, и библиотека была добавлена в LD_PRELOAD_64 и
LD_LIBRARY_PATH_64 (и также в LD_PRELOAD+LD_LIBRARY_PATH).

Java успешно запускается и вызывает нативную функцию  Java_com_jnetx_usw_chp_CHPMain_start(),
но падает при вызове throw (см. код, лог и trace ниже):

INF:17:59:33.20:CHP main(27): CHPMain.run: ok load chp library. Start it...
NOT:17:59:33.22:CHP main(27): CHPMain.run: -> chp.start
Wed Nov  8 17:59:34  CHP::startTest : cycle = 1
Wed Nov  8 17:59:35  CHP::startTest : cycle = 2
Wed Nov  8 17:59:35  Try cause Exception... 
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000000012ab5, pid=10081, tid=0x0000000000000026
#
# JRE version: Java(TM) SE Runtime Environment (8.0_121-b13) (build 1.8.0_121-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode solaris-amd64
compressed oops)
# Problematic frame:
# C  0x0000000000012ab5
#
# Core dump written. Default location: /home/kcc_64/x2001/bin/core or core.10081
#
# An error report file with more information is saved as:
# /home/kcc_64/x2001/bin/hs_err_pid10081.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#


Код был упрощен до одного потока, который через х секнерит исключение:

JNIEXPORT void JNICALL Java_com_jnetx_usw_chp_CHPMain_start
  (JNIEnv *env, jobject jobj, jint trc_level,jobjectArray j_argv,jobject chp_main,jobject
chp_smp)
{
    chp = new CHP();
    chp->startTest();
}

void CHP::startTest() {
    int t = 1;

    while (true) {
        try {
            poll(NULL, 0, 1000);
            fprintf(stderr, "%s CHP::startTest : cycle = %d\n", getTime(), t++);

            if ( 3 == t ) {
                fprintf(stderr, "%s :  Try generate Exception... \n", getTime());
                throw 20;
            }
        }
        catch (const int & e) {
            fprintf(stderr, "%s :  Catch, e = %d\n", getTime(), e);
            break;
        }
        catch (...) {
            fprintf(stderr, "%s : Catch unknown exception...\n", getTime());
            break;
        }
    }
    fprintf(stderr, "%s :  CHP::startTest : End thread, exit\n", getTime());
}


И ещё вопрос. Почему обработка попадает не в catch блок а сразу в __cxa_throw()?

pflags core
/38:   flags = DETACH
        sigmask = 0xfffffeff,0x0000ffff  cursig = SIGABRT

pstack core
 fffffd7fff291aea _lwp_kill () + a
 fffffd7fff236c39 raise () + 19
 fffffd7fff215bb0 abort () + 90
...
 fffffd7ffe9d0343 JVM_handle_solaris_signal () + 8d7
 fffffd7ffe9c8617 signalHandler () + 2f
 fffffd7fff28c2e6 __sighndlr () + 6
 fffffd7fff280bc2 call_user_handler () + 252
 fffffd7fff280dee sigacthandler (b, fffffd7f7e2f5208, fffffd7f7e2f4ea0) + ee
 --- called from signal handler with signal 11 (SIGSEGV) ---
 0000000000013dd5 ???????? () + 28000d930d5
 fffffd7fff2904d9 _SUNW_Unwind_RaiseException () + 46
 fffffd7f7dea2c53 __cxa_throw () + 9b                      !!!!!!!!!
 fffffd7f7f213310 _ZN3CHP9startTestEv () + 190
 fffffd7fee215a14 * com/jnetx/usw/chp/CHPMain.start(I[Ljava/lang/String;Lcom/jnetx/usw/chp/CHPMain;Lcom/jnetx/usw/chp/CHPSmp;)V+0
 fffffd7fee2083b6 * com/jnetx/usw/chp/CHPMain.run([Ljava/lang/String;Lcom/jnetx/usw/chp/CHPUpdateListener;)V+563
(line 377)
 fffffd7fee2083b6 * com/jnetx/usw/chp/CHPProvider$1.run()V+20 (line 374)
 fffffd7fee2007a7 * com/jnetx/usw/chp/CHPProvider$1.run()V+17760
 fffffd7ffe4c10ff __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_
() + 8d7
 fffffd7ffe4bcd3c __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_pnGSymbol_5pnRJavaCallArguments_pnGThread__v_
() + 424
 fffffd7ffe4bd124 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_pnGSymbol_6pnGThread__v_
() + 60
 fffffd7ffe64030c __1cMthread_entry6FpnKJavaThread_pnGThread__v_ () + b8
 fffffd7ffebd9679 __1cKJavaThreadDrun6M_v_ () + 5e1
 fffffd7ffe9bdc85 java_start () + 175
 fffffd7fff28bfbb _thr_setup () + 5b
 fffffd7fff28c1e0 _lwp_start ()


Компоновка тестового приложения:

g++ -g -O2  -m64 -DSOLARIS -DSUNI386 -m64  -D_REENTRANT -fPIC -DTSD   -Wall -Wextra
-std=c++0x  -shared -o libchp.so ../tmp/memtest.o   -L../tmp -lpthread -lrt -lsocket
-lposix4 -lumem -ldemangle -lrt

    -bash-3.00$ ldd libchp.so
            libstdc++.so.6 =>        /usr/local/gcc4/lib/amd64/libstdc++.so.6
            libgcc_s.so.1 =>         /usr/local/gcc4/lib/amd64/libgcc_s.so.1


Библиотеки, загруженные процессом java

lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 nfs.311.1559.269661 -> /home/kcc_64/x2001/lib/native/sunos/i386/libchp.so
...
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.233011 -> /opt/omni/library/libgcc_s.so.1
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.233028 -> /opt/omni/library/libstdc++.so.6
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.262550 -> /usr/jdk1.8.0_121/jre/lib/amd64/server/libjvm.so
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.3355 -> /usr/lib/amd64/libCrun.so.1
...
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.9059 -> /lib/amd64/libmd.so.1
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.9061 -> /lib/amd64/libmp.so.2
lrwxrwxrwx   1 vb rnd1  0 Nov  9 11:03 ufs.30.0.9062 -> /lib/amd64/libnsl.so.1

    


Ответы

Ответ 1



Проблема была решена: Существует известная проблема с небольшим несоответствием в ABI между libgcc_s.so: _Unwind_RaiseException и Solaris libc.so: _Unwind_RaiseException. Привязаться (binding) к символам среды выполнения GCC вначале приведет к тому что они загрузятся до времени выполнения Solaris, и все будет работать хорошо. Простое добавление к нашей общей библиотеки ссылки при линковке не помогло. ABI - англ. application binary interface, двоичный (бинарный) интерфейс приложений — набор соглашений для доступа приложения к операционной системе и другим низкоуровневым сервисам, спроектированный для переносимости исполняемого кода между машинами, имеющими совместимые ABI. There is a known issue with a slight mismatch in the ABI between these two (libgcc_s.so: _Unwind_RaiseException and Solaris libc.so: _Unwind_RaiseException). Binding symbols to the GCC runtime first causes it to be loaded before the Solaris runtime, and everything works out well. But, simply adding this explicitly to our shared library link line did not help anything. поэтому простой воркэраунд для этой проблемы: LD_PRELOAD=/usr/sfw/lib/amd64/libgcc_s.so Главная причина была в версии gcc, я использовал версию 4.4, а эта бага была исправлена в версии 4.9 Смешивание раскрутки стэка в libc и libgcc_s на 64-bit Solaris 10+/x86 приводит к краху

вторник, 31 декабря 2019 г.

Производительность JNI: правда или миф?

#java #cpp #jni


С учебы мне говорят то, что JNI это c++. И по скорости выполнения он превосходит
Java. Но капаюсь я в нём и, как оказалось, вызов JNI это очень трудаемкая задача. И
она требует до 12 проходов (шагов). Стоит ли вообще его использовать? И есть ли конкретные
случаи когда он в Java так необходим?
    


Ответы

Ответ 1



Прямо с сайта Oracle: Примеры, когда следует использовать JNI: Стандартная библиотека JAVA не поддерживает платформенно-специфические возможности, требуемые конкретным приложением. У вас уже есть библиотека, написанная на другом языке, и вы хотите использовать ее в JAVA. Вы хотите реализовать некоторые участки кода, критичные к скорости исполнения, на языке более низкого уровня типа Ассемблера. Пример: граф обработки аудио/видео с фильтрами. Фильтр имеет интерфейс JAVA-объекта, а алгоритм конкретного фильтра реализован на C/ASM и подключается с помощью JNI.

пятница, 27 декабря 2019 г.

Передача параметров в native-методе

#eclipse #jni #java #c #cpp


Есть функция на С (модуль traverser.c):
long int
Traverser(const char * sTraversingRoot) 
{
    long int nCount;
    struct stat rStatBuf;
    time_t nTime;
    char sActualPath[512];
    PGconn *pConn;

    // Open DB connection
    sprintf(sConnInfo, 
        "hostaddr=%s port=%s connect_timeout=50 dbname=%s user=%s password=%s",
        sIP, sPort, sDBName, sLogin, sPassword);
    pConn = PQconnectdb(sConnInfo);
    if (PQstatus(pConn) == CONNECTION_BAD) {
        AddErrorToLog("No connect\n");
        return 0;
    }

    GetActualPath(sActualPath, sTraversingRoot);

    if (*sActualPath) {
        stat(sActualPath, &rStatBuf);
    } else {
        stat("/", &rStatBuf);
    }

    if (nClock)
        nTime = time(NULL);

    if(S_ISREG(rStatBuf.st_mode)) {
        nCount = 1;
        ProcessFile(pConn, sActualPath);
    }

    if(S_ISDIR(rStatBuf.st_mode)) {
        nCount = _Traverser(pConn, sActualPath);
    }

    if (nClock)
        fprintf(stdout, "Total time : %u second(s)\n", time(NULL) - nTime);
    // Close DB connection
    PQfinish(pConn);

    return nCount;
}

Я хочу создать одноименный native-метод на Java
public native void Traverser(String path)

Соответственно в модуле traverser.c будет функция 
JNIEXPORT void JNICALL Java_ParallelIndexation_Traverser(JNIEnv *env, jobject obj,
jstring path)

Функция Java_ParallelIndexation_Traverser является оберткой функции Traverser из
модуля traverser.c. Возникает вопрос: как вызвать Traverser из модуля traverser.c в
Java_ParallelIndexation_Traverser, передав ей параметр jstring path, при этом преобразовав
его в const char * (сигнатуру Traverser см. выше)?  
    


Ответы

Ответ 1



Ты что-то замудрил с вопросом, если я правильно тебя понял, попробуй так: JNIEXPORT void JNICALL Java_ParallelIndexation_Traverser(JNIEnv *env, jobject obj, jstring path) { char* cstr = env->GetStringUTFChars(path, NULL); long result = Traverser(cstr) env->ReleaseStringUTFChars(path, cstr); }

воскресенье, 1 декабря 2019 г.

Для чего в классе Object некоторые методы имеют модификатор native?

#java #c #jni


Зачем в Java нужен модификатор native и для чего в классе Object некоторые методы
помечены им?
    


Ответы

Ответ 1



native указывает, что метод реализуется не в Java коде. В связке с JNI (Java Native Interface) идёт. Как правило, подразумевается, что метод реализован в c коде. Работа с диском, сеть и т.п. реализованы в Си части, и Java обёртки вызывают эти методы. Под рукой сейчас только Ubuntu. Пример на ней покажу. Есть у вас основной Java файл Main.java: public class Main { public native int intMethod(int i); public static void main(String[] args) { System.loadLibrary("Main"); System.out.println(new Main().intMethod(4)); } } И c файл Main.c: #include #include "Main.h" JNIEXPORT jint JNICALL Java_Main_intMethod (JNIEnv *env, jobject obj, jint i) { return i * 2; } Ещё Makefile для сборки: .PHONY: all clean all: javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I$${JAVA_HOME}/include -I$${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main clean: rm -f *.class *.so Main.h Запустим всё это дело: javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ -I${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main На экране увидите: 8. Предварительные настройки: Установлен jdk, самой собой. Установить essential: sudo apt-get install build-essential. Путь прописать до Java. У меня это export JAVA_HOME='/usr/java/jdk1.8.0_131' Пример показывает, как из Java вызвать Си код и вернуть результат. Когда это надо? OS зависимые вещи. Какие-то сложные вычисления. Часто математические библиотеки написаны на Си.

пятница, 12 апреля 2019 г.

Java вызов WinApi функций или управление открытыми окнами чужих программ

Здравствуйте!
Есть программа написанная на JAVA(модуль запускаемый как надстройка одновременно со сторонним приложением).
Из этой java-программы (надстройки), необходимо менять заголовок окон сторонней программы.
Я имею неплохие навыки программирования на java, но с подобными задачами еще не сталкивался. Я знаю, что есть JNI и JNA и куча сторонних библиотек, но в этой области я пока не опытен.
Без проблем могу решить данную задачу на С++ или на Delphi.
Но задача состоит в том, чтобы сделать изменение заголовка чужой программы средствами JAVA
Начальство очень не хочет плодить в проекте модули написанные не полностью на java (если никак по-другому - смирятся)
Рассматриваю варианты по отлову handle, заголовков окна, по id-процесса, по классу окна... Боже! да как угодно -главное чтобы работало!
С радостью приму от вас советы, ссылки, комментарии, и кусочки кода.
Было бы отлично, если кто-то поделится исходником подобной задачи.
Примеры с JNA , JNI приму с радостью!


Ответ

Конечно, JNA — это ваш выбор. Надо скачать две JAR-ки здесь, либо подключить через maven. Вот набросал пример:
import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIOptions;
public class SetWindowTitle { public static interface User32 extends StdCallLibrary { final User32 instance = (User32) Native.loadLibrary ("user32", User32.class, W32APIOptions.UNICODE_OPTIONS); HWND FindWindow(String className, String windowName); boolean SetWindowText(HWND hwnd, String newText); }
public static void main(String[] args) { if(args.length != 2) { System.out.println("Нужно два аргумента: имя окна (или класс) и новое имя"); return; } HWND hwnd = User32.instance.FindWindow(args[0], null); if(hwnd == null) { hwnd = User32.instance.FindWindow(null, args[0]); } if(hwnd == null) { System.out.println("Окно не найдено"); return; } System.out.println("Нашли окно: "+hwnd); boolean result = User32.instance.SetWindowText(hwnd, args[1]); System.out.println(result ? "Успешно" : "Упс"); } }
Компилировать:
javac -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle.java
Запускать
java -cp jna-4.1.0.jar;jna-platform-4.1.0.jar;. SetWindowTitle "old-title" "new-title"
JNA очень удобно работает. Вы просто объявляете в вашем интерфейсе методы с теми же именами, что в user32 и с совместимой сигнатурой. Внутри JNA создаёт Proxy-класс, который для каждого метода поищет соответствующий внутри user32.dll и преобразует нужным образом аргументы.

пятница, 21 декабря 2018 г.

Производительность JNI: правда или миф?

С учебы мне говорят то, что JNI это c++. И по скорости выполнения он превосходит Java. Но капаюсь я в нём и, как оказалось, вызов JNI это очень трудаемкая задача. И она требует до 12 проходов (шагов). Стоит ли вообще его использовать? И есть ли конкретные случаи когда он в Java так необходим?


Ответ

Прямо с сайта Oracle
Примеры, когда следует использовать JNI:
Стандартная библиотека JAVA не поддерживает платформенно-специфические возможности, требуемые конкретным приложением. У вас уже есть библиотека, написанная на другом языке, и вы хотите использовать ее в JAVA. Вы хотите реализовать некоторые участки кода, критичные к скорости исполнения, на языке более низкого уровня типа Ассемблера.
Пример: граф обработки аудио/видео с фильтрами. Фильтр имеет интерфейс JAVA-объекта, а алгоритм конкретного фильтра реализован на C/ASM и подключается с помощью JNI.

понедельник, 8 октября 2018 г.

Для чего в классе Object некоторые методы имеют модификатор native?

Зачем в Java нужен модификатор native и для чего в классе Object некоторые методы помечены им?


Ответ

native указывает, что метод реализуется не в Java коде. В связке с JNI (Java Native Interface) идёт.
Как правило, подразумевается, что метод реализован в c коде. Работа с диском, сеть и т.п. реализованы в Си части, и Java обёртки вызывают эти методы.
Под рукой сейчас только Ubuntu. Пример на ней покажу.
Есть у вас основной Java файл Main.java
public class Main { public native int intMethod(int i); public static void main(String[] args) { System.loadLibrary("Main"); System.out.println(new Main().intMethod(4)); } }
И c файл Main.c
#include #include "Main.h"
JNIEXPORT jint JNICALL Java_Main_intMethod (JNIEnv *env, jobject obj, jint i) { return i * 2; }
Ещё Makefile для сборки:
.PHONY: all clean
all: javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I$${JAVA_HOME}/include -I$${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main
clean: rm -f *.class *.so Main.h
Запустим всё это дело:
javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ -I${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main
На экране увидите: 8
Предварительные настройки:
Установлен jdk, самой собой. Установить essential: sudo apt-get install build-essential Путь прописать до Java. У меня это export JAVA_HOME='/usr/java/jdk1.8.0_131'
Пример показывает, как из Java вызвать Си код и вернуть результат.
Когда это надо?
OS зависимые вещи. Какие-то сложные вычисления. Часто математические библиотеки написаны на Си.