<< index
< bölüm 13
> bölüm 15
Java programlama dili C dilinde yazılmıştır. Bu yüzden C’den javaya geçiş oldukça kolay bir şekilde yapılabilir. Bir örnekle birden fazla programlama dilinin nasıl kullanılabildiğine bakmadan önce, bir temel kavramı iyi anlamamız gerekir. Java güvenlik açısından maksimum güvenliği verebilen bir dildir. Öte taraftan C maksimum hızlara ulaşmayı sağlayabilen bir dildir. C programlarını java programlarıyla birlikte kullanmamızın temel nedeni hız gereken yerlerde bu hızı sağlamaktır. Ancak hız sağlarken güvenlikten olan kaybımızı her zaman hesaba katmamız ve ikisi arasında bir denge bulmamız biz programcılara bırakılmıştır. Bu yüzden iki dilli programlamada oldukça dikkatli bir şekilde çalışma gereksinimi oluşturur. Bu konu C++ dilini iyi bilen programcılar içindir. Burada C programlamasına girmeyeceğiz. Eğer bu dili bilmiyorsanız, bu konuya başlamadan önce öğrenmenizi veya java anadil programlamasını hiç kullanmamanızı tavsiye ederim. C++ dilini kullanabilmek için, hele iki dili bir arada kullanabilmek için iyi bir programcı olmanız gerekiyor, eğer kendinizi güveniyorsanız, bundan sonraki kısma geçebilirsiniz.
14.2 Örnek problemle step step iki dilli program kodunun hazırlanması ve çalıştırılması
Çok dilli programlama birden fazla basamağı gerektiren bir prosestir. Bir örnek problemler bu basamakları inceleyelim :
C++ dili ile java dilinin beraber çalışacağı bir örnek oluşturalım. İlk step olarak java dilindeki programımızı yazalım :
Program 14.1 JavaCpp.java programı
class JavaCpp
{
public native void cdenaktar();
static
{
System.loadLibrary("jcpp");
}
public static void main(String[] args)
{
new JavaCpp().cdenaktar();
}
}
JavaCpp programında iki temel metod görüyoruz. Birinci metod cdenaktar() metodudur. Bu metod biraz sonra C++ dilinde oluşturacağımız fonksiyonu Java’nın bir parçası olarak çağırır. İkinci metod ise main metodudur. Cdenaktar metoduna bakarken bunun java metodu olmadığını belirten native sözcüğü yer almaktadır. Metodun türü void’dir, yani hiçbir şey aktarılmıyacaktır. Programımızı, herhangi bir java programında olduğu gibi önce
java JavaCpp.java
Komutunu kullanarak derleriz. İkinci stepte javah komutunu kullanarak
javah JavaCpp
JavaCpp.h dosyasını oluştururuz. Bu dosyanın içeriği :
Program 14.2 JavaCpp.h arabağlantı programı
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JavaCpp */
#ifndef _Included_JavaCpp
#define _Included_JavaCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JavaCpp
* Method: cdenaktar
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JavaCpp_cdenaktar
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
şeklinde olacaktır. Bundan
sonraki stepte C++ dilinde aşağıdaki programı oluşturalım :
Program 14.3 JavaCpp_c.cpp C++ programı
#include <iostream.h>
#include <jni.h>
#include "JavaCpp.h"
JNIEXPORT void JNICALL
Java_JavaCpp_cdenaktar(JNIEnv *env, jobject obj)
{
cout<<"Java-C++ programlama dillerini birlikte kullanıyoruz ";
return;
}
c++ programını derlemek için elbette bir derleyiciye ihtiyaç vardır. Biz burada MS Visual C++ versiyon 6 derleyicisini kullandık, herhangi bir dll dosyası hazırlayan derleyici (MS Windows için) aynı işi görebilir.
Bu derleyici ile derleme için ya direk olarak dos’ta
cl -Ic:\co\java\include -Ic:\co\java\include\win32 -LD %JavaCpp_c.cpp –Fejcpp.dll
komutunu kullanırız, yada bu uzun komutu her sefer yazmamak için bir isim.bat dosyası yaratıp bunu kullanabiliriz. Örneğin hazırladığımız pcomp.bat dosyası
Program 14.4 pcomp.bat MSdos programı
cl -Ic:\co\java\include -Ic:\co\java\include\win32 -LD %1.cpp -Fe%2.dll
kullanılarak yukarıdaki komut
pcomp JavaCpp_c jcpp
şeklinde verilebilir. Bu işlemleri yaptığımızda programımız çalışmaya hazır olacaktır. Programı çalıştırmak için :
java JavaCpp
komutunu kullanmamız yeterli olacaktır. Program çıktısı :
Java-C++ programlama dillerini birlikte kullanıyoruz
Şeklinde olacaktır. Burada derlemenin jcpp.dll dosyasına yapıldığını hatırlatalım, ve bu dosya java programı üzerinden C++ metodunu çalıştırırken kullandığımız ana programdı.
İlk programımızda java ve C++ arasında herhangi bir değişken aktarılması olmamış, sadece void türü fonksiyon kullanılarak belli bir yazı yazan C++ fonksiyonu çağırılmıştır. İkinci örneğimizde java programımızdan String türü değişkeni C++ programlama diline aktaracak ve kullanacağız.
İlk java programımız Showmessage.java. bu programda ekrandan girilen bir string, yahut ekrandan girilen bir string değeri yoksa programın içinde tanımlanan bir stringle birlikte C++ programına aktarılıp burada ekrana yazılmaktadır.
Program 14.5 ShowMessage.java programı
public class ShowMessage {
private native void ShowMessage(String msg);
static { System.loadLibrary("MsgI"); }
public static void main(String[] args) {
ShowMessage app = new ShowMessage();
if(args.length==0)
app.ShowMessage("Bu mesaj javadan C++ ya gönderildi ve orada yazıldı");
else
app.ShowMessage(args[0]);
}
}
bu program javac ShowMessage.java ve javah ShowMessage komutlarıyla işlendikten sonra
Program 14.6 MsgImpl.cpp programı
//dosya : MsgImpl.cpp
#include <jni.h>
#include <iostream.h>
#include <stdio.h>
#include "ShowMessage.h"
extern "C" JNIEXPORT void JNICALL
Java_ShowMessage_ShowMessage(JNIEnv* env,
jobject, jstring jMsg)
{
const char* msg=env->GetStringUTFChars(jMsg,0);
printf("JNI cikti stringi : %s\n",msg) ;
env->ReleaseStringUTFChars(jMsg, msg);
}
c++ dilindeki MsgImpl.cpp programı hazırlanmış ve
üstte hazırladığımız pcomp.bat yardımıyla
pcomp MsgImpl MsgI
komutu kullanılarak derlenmiştir. Program çıktısı
java ShowMessage “Merhaba Dünya” komutu kullanılarak :
JNI cikti stringi : Merhaba Dünya
veya
java ShowMessage komutu kullanılarak
JNI cikti stringi : Bu mesaj javadan C++ ya gönderildi ve orada yazdırıldı
Çıktısı alınabilir. Programda veri aktarımı yapmak amacıyla java tarafında metod tanımı yapılırken
private native void ShowMessage(String msg);
tanımı verilmiştir. Buradaki String msg metodun dolayısıyla C++ fonksiyonunun girdisini teşkil etmektedir. C++ tarafında mesajı alırken,
Java_ShowMessage_ShowMessage(JNIEnv* env,
jobject, jstring jMsg)
{
const char* msg=env->GetStringUTFChars(jMsg,0);
jstring jMsg tanımıyla aktarılmış ve const char* msg=env->GetStringUTFChars(jMsg,0);
tanımıyla c değişkenine dönüştürülmüştür.
Javada Stringler unicode (16 bit) olarak tanımlanmıştır. C stringleri ise 8 bitlik ascii char boyutlu değişkeni olarak tanımlanır. Bu yüzden string değişkenlerini javadan cye veya cden javaya aktarırken dönüşümler yapmak gerekir. Aynı zamnda java string değişkenleri length (boyut) değişkenini de bünyelerinde taşırlar. Cde ise boyut tanımlanmamıştır. Ayrı bir değişken üzerinden tanımlanması gerekebilir. Bu dönüşümleri yapmak için bir dizi metod tanımlanmıştır.
Bu tanımaların tamamı şöyledir :
GetStringChars
GetStringLength
GetStringUTFChars
GetStringUTFLength
NewString
NewStringUTF
ReleaseStringChars
ReleaseStringUTFChars
Buradaki ikinci örneğimizde java programında c++ dilindeki bir fonksiyonun (metod) yaptığı hesap sonuçlarını aktaracağız. Programımız java’da çağırılan bir C++ kare metodunu kullanarak java dilinde girilen sayının karesini hesaplayacaktır.
Program 14.7 karesinifi.java programı
class karesinifi {
private native double kare(double x);
public static void main(String args[]) {
karesinifi p = new karesinifi();
double x=2.0;
double y = p.kare(x);
System.out.println("" +x+" kare = "+ y);
}
static {
System.loadLibrary("kareI");
}
}
bu programı javac karesinifi.java deyimiyle derleyip, javah karesinifi deyimiyle anadil kütüphanesine çevirirsek
Program 14.8 karesinifi.h programı
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class karesinifi */
#ifndef _Included_karesinifi
#define _Included_karesinifi
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: karesinifi
* Method: kare
* Signature: (D)D
*/
JNIEXPORT jdouble JNICALL Java_karesinifi_kare
(JNIEnv *, jobject, jdouble);
#ifdef __cplusplus
}
#endif
#endif
karesinifi.h bize java programındaki
private native double kare(double x);
metodunun c++ anadil (Native) karşılığının
JNIEXPORT jdouble JNICALL Java_karesinifi_kare
(JNIEnv *, jobject, jdouble);
olduğunu göstermektedir. Şimdi kare metodunun aslını C++ dilinde yazarsak :
Program 14.9 karesinifi.cpp C++ programı
#include <stdio.h>
#include <jni.h>
#include "karesinifi.h"
JNIEXPORT jdouble JNICALL Java_karesinifi_kare(JNIEnv *, jobject, jdouble x )
{
return x*x;
}
burada metod isminin kare yerine Java_karesinifi_kare şeklini aldığını görüyoruz. Double değişkeni de yerini jdouble değişkenine bırakmış durumda. Java anadilinde programları yazarken metod isimleri
Java_sınıfismi_metodismi
Şeklini alır. Basit java değişkenlerinin Anadil karşılıkları ise
Tablo 14.1 Java değişken tipleri ve ana dil (native) eşdeğerleri
Java değişken tipi |
Anadil (Native) değişken eşdeğeri |
Değişken bit değeri |
Boolean |
jboolean |
8, işaretsiz |
Byte |
jbyte |
8 |
Char |
jchar |
16, işaretsiz |
Short |
jshort |
16 |
Int |
jint |
32 |
Long |
jlong |
64 |
Float |
jfloat |
32 |
Double |
jdouble |
64 |
Object |
jobject |
|
Void |
void |
Yok |
Şeklindedir. C++ programı
pcomp karesinifi kareI
deyimiyle veya açık yazılışıyla
cl -Ic:\co\java\include -Ic:\co\java\include\win32 -LDkaresinifi.cpp –KareI.dll
deyimiyle derlenirse (MS Visual C++ 6), sonuç :
2.0 kare = 4.0
şeklinde çıkacaktır.
Şimdi de bu işlemin tam tersini inceleyelim. Java’da yazılmış olan kare metodunu C++ ve C dillerinde çağıralım.
Java programımız karesinifi1.java aşağıdaki gibi tanımlanmıştır.
Program 14.10 karesinifi1.java java programı
class karesinifi1 {
private native void nativeMethod();
private double kare(double x)
{
return x*x;
}
public static void main(String args[])
{
karesinifi1 c=new karesinifi1();
c.nativeMethod();
}
static {
System.loadLibrary("kare1I");
}
}
sınıfın alt sınıfı olan kare’de girilen sayının karesi hesaplanmaktadır. NativeMethod metodu da C (veya c++) dilleriyle bağlantı sağlamaktadır. Metodumuzu yine java karesinifi1.java ile derledikten sonra javah karesinifi1 komutuyla karesinifi1.h dosyasını oluştururuz. Bu dosya :
Program 14.11 karesinifi1.h programı
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class karesinifi1 */
#ifndef _Included_karesinifi1
#define _Included_karesinifi1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: karesinifi1
* Method: nativeMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_karesinifi1_nativeMethod
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
anadil tarafında program yazılırken bize yardımcı olabilecek bir ara java programı javap de mevcuttur.
Bu işlemi yapmak zorunda değiliz. Yapma sebebimizi c++ dili programını inceleyince daha iyi anlayacaksınız.
javap -s -p karesinifi1
Program 14.12 javap komutuyla oluşturulan ara kod
Compiled from karesinifi1.java
class karesinifi1 extends java.lang.Object {
karesinifi1();
/* ()V */
private native void nativeMethod();
/* ()V */
private double kare(double);
/* (D)D */
public static void main(java.lang.String[]);
/* ([Ljava/lang/String;)V */
static {};
/* ()V */
}
şimdi c++ koduna bakalım :
Program 14.13 karesinifi1.cpp programı
#include <stdio.h>
#include <iostream.h>
#include <jni.h>
#include "karesinifi1.h"
JNIEXPORT void JNICALL Java_karesinifi1_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls=env->GetObjectClass(obj);
jmethodID mid=env->GetMethodID(cls,"kare","(D)D");
double x=2.0;
double y=env->CallDoubleMethod(obj,mid,x);
cout<<x<<"nin karesi = "<<y;
}
Bu programda önce java sınıfının (karesinifi1) aktarılması jobject obj değişkeni ve
jclass cls=env->GetObjectClass(obj);
üzerinden yapılır. Burada sınıf adresi cls değişkenine yüklenmiş olur. Alt metod karenin tanımı için
jmethodID mid=env->GetMethodID(cls,"kare","(D)D");
tanımı kullanılmıştır. Buradaki “(D)D” tanımı program 14.12 de bize verilmişti. Anlamı java programındaki kare metodunun double değişken girişi olduğu ve çıkışında double değişken istediğidir. “kare” deyimiyle metodun javadaki ismi verilmiştir. Cls ise üstte tanımladığımız karesinifi1 java sınıfının adresine belirtmektedir.
double y=env->CallDoubleMethod(obj,mid,x);
deyimiyle de metodu çağırıp sonuçlarını y değişkenine yüklemekteyiz.
Burada kullandığımız D işareti java değişken türünün double olduğunu belirtiyordu. Java değişken tiplerinin işaret karşılıkları Tablo 14.2 de verilmiştir.
Tablo 14.2 Java tiplerinin eşdeğer işaretleri
İşaret |
Java değişken tipi |
Z |
boolean |
B |
Byte |
C |
Char |
S |
Short |
I |
Int |
J |
Long |
F |
Float |
D |
Double |
L sınıf ismi |
sınıf ismi |
[Değişken türü |
Değişken türü[] |
Bu programda sınıfı çağırmak için GetObjectClass metodu, metodu tanımlamak içinde GetMethodID metodunu kullandık. CallDoubleMethod metodu ile de metodu çalıştırdık. Paralel işlemleri yapmak için mevcut olan metod listesi ve anlamları şöyledir :
GetObjectClass : sınıf adresini tanımlar
GetMethodID : dinamik metod adresini tanımlar
GetStaticMethodID : statik metod adresini tanımlar
Call<değişkentürü>Method : çeşitli metodları çağırır
CallBooleanMethod
CallByteMethod
CallCharMethod
CallDoubleMethod
CallFloatMethod
CallIntMethod
CallLongMethod
CallObjectMethod
CallShortMethod
CallVoidMethod
CallStatic< değişkentürü >Method : statik metodları çağırır, değişken türleri olarak yukaridakinin aynı
türleri kabul eder.
CallNonvirtual< değişkentürü >Method
Call< değişkentürü >MethodV
Call< değişkentürü >MethodA
Aynı programın c dilinde yazılması küçük farklılıklar taşır. C dilideki program :
Program 14.14 karesinifi1.c programı
#include <stdio.h>
#include <jni.h>
#include "karesinifi1.h"
JNIEXPORT void JNICALL Java_karesinifi1_nativeMethod(JNIEnv *env, jobject obj)
{
jclass cls=(*env)->GetObjectClass(env,obj);
jmethodID mid=(*env)->GetMethodID(env,cls,"kare","(D)D");
double x=2.0;
double y=(*env)->CallDoubleMethod(env,obj,mid,x);
printf("%f nin karesi = %f ",x,y);
}
programdan da görüldüğü gibi C++ daki :
jclass cls=env->GetObjectClass(obj);
komutu
jclass cls=(*env)->GetObjectClass(env,obj);
halini almıştır.
jmethodID mid=env->GetMethodID(cls,"kare","(D)D");
komutu
jmethodID mid=(*env)->GetMethodID(env,cls,"kare","(D)D");
halini almıştır.
double y=env->CallDoubleMethod(obj,mid,x);
komutu ise
double y=(*env)->CallDoubleMethod(env,obj,mid,x);
halini almıştır. Sonuç olarak env yerine referans değişkeni (*env) gelmektedir ve env referans değişkeni aynı zamanda metod değişkeni olarakda çağırılmaktadır. Bunun dışında işlemler arasında bir fark yoktur.
Program java karesinifi1 deyimiyle çalıştırıldığında
2nin karesi = 4
sonucunu alırız.
İkinci bir sınıf ulaşım örneği olarak UseObjects programını verelim. Burada sınıf, MyJavaClass içinde bir int değişken ve bir void metod mevcuttur. İkinci bir metod olan UseObjects metodu kullanılarak native metod changeObject’e ulaşılmakta ve bu metod c++ programında kullanılarak sonuçlar hesaplanmaktadır.
Program 14.15 UseObjects.java programı
//UseObjects.java
class MyJavaClass {
public int aValue;
public void divByTwo() { aValue /= 2; }
}
public class UseObjects {
private native void
changeObject(MyJavaClass obj);
static {
System.loadLibrary("UseObjImpl");
}
public static void main(String[] args) {
UseObjects app = new UseObjects();
MyJavaClass anObj = new MyJavaClass();
anObj.aValue = 2;
app.changeObject(anObj);
System.out.println("Java: " + anObj.aValue);
}
}
Program 14.16 javah UseObject komutu kullanılarak oluşturulan UseObjects.h programı
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class UseObjects */
#ifndef _Included_UseObjects
#define _Included_UseObjects
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: UseObjects
* Method: changeObject
* Signature: (LMyJavaClass;)V
*/
JNIEXPORT void JNICALL Java_UseObjects_changeObject
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
Program 14.17 UseObjImp.cpp programı
#include <jni.h>
extern "C" JNIEXPORT void JNICALL
Java_UseObjects_changeObject( JNIEnv* env, jobject, jobject obj)
{
jclass cls = env->GetObjectClass(obj);
jfieldID fid = env->GetFieldID(cls, "aValue", "I");
jmethodID mid = env->GetMethodID(cls, "divByTwo", "()V");
int value = env->GetIntField(obj, fid);
printf("Native: %d\n", value);
env->SetIntField(obj, fid, 6);
env->CallVoidMethod(obj, mid);
value = env->GetIntField(obj, fid);
printf("Native: %d\n", value);
}
Program 14.15 de tanımlanan MyJavaClass sınıfı bir int değişken, aValue, ve bir metod, divByTwo , içermektedir. Metod int de verilen değeri 2 ye bölmekte ve sonucu aktarmaktadır. Bu programda int sınıf alt değişkenini tanımlamak için
jfieldID fid = env->GetFieldID(cls, "aValue", "I");
deyimini kullandık. Void aValue metodu
jmethodID mid = env->GetMethodID(cls, "divByTwo", "()V");
deyimiyle tanımlandı. Ve
env->SetIntField(obj, fid, 6);
tanımıyla 6 değeri atandı.
Sınıfların alt değişkenlerine değer atamak (ve okumak )için
GetFieldID
GetStaticFieldID
Get< değişkentürü >Field
GetBooleanField
GetByteField
GetCharField
GetDoubleField
GetFloatField
GetIntField
GetLongField
GetObjectField
GetShortField
Set< değişkentürü >Field
GetStatic< değişkentürü >Field
SetStatic< değişkentürü >Field
Metodları mevcuttur.
Şimdi de Çok boyutlu değişkenleri nasıl kullanabildiğimizi inceleyelim :
Program 14.18 IntArray.java programı
class IntArray {
private native int sumArray(int arr[]);
public static void main(String args[]) {
IntArray p = new IntArray();
int arr[] = new int [10];
for (int i = 0; i < 10; i++)
arr[i] = i;
int sum = p.sumArray(arr);
System.out.println("sum = " + sum);
}
static {
System.loadLibrary("MyImpOfIntArray");
}
}
Program 14.19 IntArray.c programı
#include <jni.h>
#include "IntArray.h"
JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jsize len = (*env)->GetArrayLength(env, arr);
int i, sum = 0;
jint *body = (*env)->GetIntArrayElements(env, arr, 0);
for (i=0; i<len; i++) {
sum += body[i];
}
(*env)->ReleaseIntArrayElements(env, arr, body, 0);
return sum;
}
burada tanımlanan java programında boyutlu değişken arr tanımlanmış, ve boyutlu değişkenin toplamı c programında hesaplanmıştır. C metodunda boyutlu değişkeni tanımlamak için jintArray türü arr değişkeni kullanılmıştır. Boyutlu değişkenin boyutu jsize tipi len değişkenine
jsize len = (*env)->GetArrayLength(env, arr);
deyimiyle aktarılmıştır.
arr değişkeninin değeri jint tipi body boyutlu değişkene, indeksi 0dan başlamak üzere
jint *body = (*env)->GetIntArrayElements(env, arr, 0);
metoduyla aktarılır.
arr boyutlu değişkeninin değeri (değerler değişmişte olabilir) tekrar kullanılabilmek üzere
(*env)->ReleaseIntArrayElements(env, arr, body, 0);
deyimi kullanılarak serbest bırakılır (javaya gönderilir). Bu işlemlerin sonucunda java programı :
sum = 45
sonucunu verecektir. JNI boyutlu değişken çağırma fonksiyonları(metodları) şöyledir :
GetArrayLength
Get< değişkentürü >ArrayElements
GetBooleanArrayElements
GetByteArrayElements
GetCharArrayElements
GetDoubleArrayElements
GetFloatArrayElements
GetIntArrayElements
GetLongArrayElements
GetShortArrayElements
Release< değişkentürü >ArrayElements
Get< değişkentürü >ArrayRegion
Set< değişkentürü >ArrayRegion
GetObjectArrayElement
SetObjectArrayElement
Java dilinde tanımlanmış, fakat c dilinde direk tanımlanmamış işlemlerden birisi de hata analiz işlemidir (Catch-throw exception). Ana dil programlaması kullanırken, bu işlemi de yapmak mümkündür. Aşağıdaki CatchThrow program setinde hata sisteminin kullanılmasını görüyoruz.
Program 14.20 CatchThrow.java programı
class CatchThrow {
private native void catchThrow() throws IllegalArgumentException;
private void callback() throws NullPointerException {
throw new NullPointerException("thrown in CatchThrow.callback");
}
public static void main(String args[]) {
CatchThrow c = new CatchThrow();
try {
c.catchThrow();
} catch (Exception e) {
System.out.println("In Java:\n " + e);
}
}
static {
System.loadLibrary("MyImpOfCatchThrow");
}
}
Program 14.21 CatchThrow.c programı
#include <jni.h>
#include "CatchThrow.h"
JNIEXPORT void JNICALL
Java_CatchThrow_catchThrow(JNIEnv *env, jobject obj)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
jthrowable exc;
if (mid == 0) {
return;
}
(*env)->CallVoidMethod(env, obj, mid);
exc = (*env)->ExceptionOccurred(env);
if (exc) {
/*
Biz aslında c’de hata konusunda gerçekten bir şey yapmıyoruz,
sadece bir mesaj iletiyoruz, hata değişkenini temizliyoruz ve
yeni bir exception gönderiyoruz. */
jclass newExcCls;
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
if (newExcCls == 0) { /* Unable to find the new exception class, give up. */
return;
}
(*env)->ThrowNew(env, newExcCls, "thrown from C code");
}
}
bu programı çalıştırdığımızda :
sonucunu alırız. Buradaki
In Java:
java.lang.IllegalArgumentException: thrown from C code
mesajı c tarafından oluşturulup gönderilmiştir.
JNI Hata fonksiyonları şunlardır :
ExceptionClear
ExceptionDescribe
ExceptionOccurred
Burada iki dilli programlama kavramına bir giriş yaptık. Buradaki kavramlar size biraz zor geldiyse lütfen umutsuzluğa kapılmayın, java ve C dillerini çok iyi öğrendikten sonra geri dönün. İki dilli programlama her zaman programlama dünyasının en zor işlerindendir, ayrıca jbuilder, Microsoft j++ gibi paketler java anadil (native) programlamasında işleri kolaylaştıran otomatik kod oluşturma sisyemleri sunarlar, bu tür programlama araçlarıyla işinizi daha kolay hale getirebilirsiniz.
<< index
< bölüm 13
> bölüm 15