Archive

Posts Tagged ‘java’

Риторический вопрос по Си.

January 27th, 2012 3 comments
int main()
{
int n;
float mas[n];
mas[0] = 6.6;
}

При запуске такой код, естественно, даст Segmentation fault, но при компиляции ничего кроме варнинга(а кто на них смотрит?) не выдаст. Visual Studio ругается сразу. Пробовал на icc, gcc, pcc.
Может все-таки переходить на яву? :)

jni и ioctl

March 23rd, 2011 No comments

Итак, я готов показать вам еще кусочик черной магии. Сегодня мы будем с вами работать с железом при помощи Java Native Interface.

Задача для меня типовая. Есть некоторая плата АЦП(хотя это может быть любое другое устройство). Для нее есть драйвер под линукс. Обмен данными с платой происходит при помощи сообщений, передаваемых через ioctl.  Необходимо эти сообщения получать в ПО, обрабатывать и посылать что-нибудь в ответ через те же ioctl.

Итак, как вы знаете, Java предоставляет средство для работы с внешними системными библиотеками, это средство – JNI. Воспользовавшись этим мощнейшим средством, мы напишем небольшую библиотеку, которая обеспечит нам взаимодействие с ioctl, который является системным вызовом и напрямую из Java недоступен.

Подготовим класс-обертку:

public class LL {

public static native int Ioctl(int descr, int cmd, int[] data);
public static native int Open(String linkName);
public static native int Close(int fd);

}

Как описано в прошлой статье сгененируем заголовочный файл для C:

$ javac LL.java
$ javah -jni LL

Не забудьте, что я убрал пути из командной строки. Вам надо будет разобраться с ними вручную.

Полученый LL.h:

/* DO NOT EDIT THIS FILE – it is machine generated */
#include
/* Header for class LL */

#ifndef _Included_LL
#define _Included_LL
#ifdef __cplusplus
extern “C” {
#endif
/*
* Class: LL
* Method: Ioctl
* Signature: (II[I)I
*/
JNIEXPORT jint JNICALL Java_LL_Ioctl
(JNIEnv *, jclass, jint, jint, jintArray);

/*
* Class: LL
* Method: Open
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_LL_Open
(JNIEnv *, jclass, jstring);

/*
* Class: LL
* Method: Close
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_LL_Close
(JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

Теперь напишем реализацию этих функций:

#include "LL.h"
#include
#include
#include

#define MAXDRVMSG 32

JNIEXPORT jint JNICALL Java_LL_Ioctl(JNIEnv *env, jclass jc, jint fd, jint cmd, jintArray data)
{
int res = -1;
if(data == NULL)
{
fprintf(stderr,"no param ioctl");
res = ioctl(fd, cmd);
}
else
{
fprintf(stderr,"with param ioctl %p\n",data);
unsigned int *x = (unsigned int *) calloc(MAXDRVMSG, sizeof(unsigned int));
res = ioctl(fd, cmd, x);
(*env)->SetIntArrayRegion(env, data, 0, MAXDRVMSG, (jint *) x);
}
fprintf(stderr,"LL_Ioctl: fd %d result %d\n",fd, res);
return res;
}

JNIEXPORT jint JNICALL Java_LL_Open(JNIEnv *env, jclass jc, jstring linkname)
{
jboolean iscopy;
const char *mfile = (*env)->GetStringUTFChars(env, linkname, &iscopy);
fprintf(stderr,"LL_Open: filename %s\n",mfile);
int fd = open(mfile, O_RDWR);
fprintf(stderr,"LL_Open: descr %d\n",fd);
return fd;
}

JNIEXPORT jint JNICALL Java_LL_Close(JNIEnv *env, jclass jc, jint fd)
{
fprintf(stderr,"LL_Close: fd %d\n",fd);
return close(fd);
}

Отличие от предыдущего эксперимента в том, что теперь мы стали получать данные из функций, описанных в нашей библиотеке. В простых случаях Close и Open проблем с возвратом не возникает, а вот в случае с Ioctl, где нам надо получать\отправлять блоки данных, а не примитивные типы без хитростей не обойтись. В данном случае хитрость в том, что для обмена с драйвером мы выделим временный буффер, в который скопируем данные из data, переданного в качестве параметра функции. После системого вызова нам надо будет скопировать данные из ответа назад в нашу виртуальную машину.

Makefile для собрки этого безобразия:

SRC=LL.c
OBJ=libll.o
LIB=libll.so

GCC=gcc

default:
$(GCC) -c $(SRC) -o $(OBJ)
$(GCC) -shared -Wl,-soname,$(LIB) -o $(LIB) $(OBJ) -lc

jni:
javac -d ../out/production/jni_hw/ ../src/LL.java
javah -jni -classpath ../out/production/jni_hw/ LL

И небольшой тестик:

public class LLtest {

public static void main(String[] args)
{
System.load(“/home/toch/src/java/jni_hw/jni/libll.so”);
int x = LL.Open(“/dev/char_dev”);
int[] msg = new int[32];
LL.Ioctl(x, 1, msg);
for(int i = 0;i<32;i++) System.out.println(String.format("0x%x",msg[i]));
LL.Close(x);
}
}

Java, JNI. Вызов методов Си из сошки средствами Java

December 24th, 2010 No comments

Java Native Interface (JNI) позволяет вызывать “родные” методы ОС из Java. Как это использовать, решать вам.
Итак, небольшой пример.
Первое, что нам необходимо, это собственно java исходник. Он будет выглядеть так:

public class jnitest {
public static native void HelloWorld();
public static void main(String[] args)
{
System.load("/home/toch/IdeaProjects/jnitest/libtestjni.so");
System.out.println("Hello from java!");
HelloWorld();
}
}

Это только пример, показывающий ключевой момент, а именно метод HelloWorld(), который мы объявляем native. Это указывает, что реализация самого метода будет находиться во вне, так сказать. Отсюда и следствие – у метода нет тела. Вообще. :)
Второй ключевой момент это вызов System.load(), который будет загружать нашу будущую тестовую библиотеку.
Скомпилировав этот файл, мы получим обычный класс: jnitest.class. Немного магии, которую надо выполнять в каталоге, где расположен этот файл:
javah -jni jnitest

Утилита создась файл jnitest.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class jnitest */

#ifndef _Included_jnitest
#define _Included_jnitest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jnitest
* Method: HelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jnitest_HelloWorld
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

Это заголовочный файл, который подсказывает нам, как яваметод превращается в метод С. Для удобства переименуем файл в libjnitest.h

Следующим шагом пишем тело нашего нативного метода в libjnitest.cpp:
#include
#include "libtestjni.h"

JNIEXPORT void JNICALL Java_jnitest_HelloWorld
(JNIEnv *, jclass)
{
fprintf(stderr,"Hello World from C!!!\n");
return;
}

Makefile, чтобы получить собственно сошку:
SRC=libtestjni.cpp
OBJ=libtestjni.o
LIB=libtestjni.so

TESTSRC=testjni.cpp

GCC=g++

default:
$(GCC) -c $(SRC) -o $(OBJ)
$(GCC) -shared -Wl,-soname,$(LIB) -o $(LIB) $(OBJ) -lc

Теперь, генерируем библиотеку выполнив make. Должны получить файл libtestjni.so.

Собственно, исправив путь в System.load(), на тот, который будет у вас(ваш домашний каталог, к примеру), можно смело запускаться. В консоле вы должны увидеть:
Hello from java!
Hello World from C!!!

Поздравляю!

Java. Опрос.

December 9th, 2010 4 comments

Кстати, такой вопрос, а у скольких из вас на компьютере установлена ява. Желательно с версией. А в браузере включена(не яваскрипт, а ява)?

заправка картриджей hp 78a в Москве | Потолочные кондиционеры MIDEA с доставкой по России.