[Go Back]
2.1 起步:以「二进制半加器」为例
在初学JNI时,一般都是从Java调用C函数开始。然后,逐渐学习到反向调用,反过来从C函数来存取Java层的对象,或调用Java层的函数。在本章里,也不利外,藉由一个简单的范例,说明一个Java程序如何透过JNI接口来调用本地(Native)的C函数。到了下一章,将会介绍更多的开发技巧。
兹设计一个半加器(HalfAdder)类别,它是用来进行二进制元(Bit: Binary Digit)的加法运算。例如,位值1和另一个位值1之加法运算,如下:
进行位加法运算时,将digit_1、digit_2两个位值输入给半加器,此时个位数运算会输出Sum和Carry值。[歡迎光臨 高煥堂 網頁:http://www.cnblogs.com/myEIT/ ]
在本节里,兹先使用Java来撰写这个二进制半加器类别和它的UI操作画面。等到下一节里,则将改用C来撰写这个半加器类别。于是,建立一个Android开发项目:
此范例的架构图,如下:
图2-1 纯粹以Java撰写的程序架构
其中,ac01提供UI画面,如下图:
这是二进制半加法的计算器画面。这ac01类别执行时,调用NativeJniAdder类别的execute()函数,转而调用HalfAdder类别的run()函数,以便进行二进制的加法运算。这NativeJniAdder.java类别的程序码如下:
// NativeJniAdder.java
package com.misoo.gx05;
public class NativeJniAdder {
public static int calculate(int digit_1, int digit_2){
HalfAdder hadder = new HalfAdder();
hadder.set_digits(digit_1, digit_2);
hadder.run();
int k = hadder.get_carry() *10 + hadder.get_sum();
return k;
}
}
同时,也撰写一个HalfAdder.java类别,其程序码如下:
// HalfAdder.java
package com.misoo.gx05;
public class HalfAdder {
private int a,b, carry, sum;
HalfAdder(){}
public void set_digits(int d1, int d2) { a = d1; b = d2; }
public void run() { carry = a & b; sum = a ^ b; }
public int get_carry(){ return carry; }
public int get_sum(){ return sum; }
}
接着,来撰写ac01.java来提供UI画面,这ac01.java的程序码为:
// ac01.java
package com.misoo.gx05;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class ac01 extends Activity implements OnClickListener {
private Button[] btn;
private int curr;
private Calculator calc;
private TextView tv;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
btn = new Button[6];
setContentView(R.layout.bi_cal_layout);
tv = (TextView)findViewById(R.id.tv);
tv.setTextColor(Color.BLACK); tv.setText("><");
btn[0] = (Button)findViewById(R.id.btn_0); btn[0].setOnClickListener(this);
btn[1] = (Button)findViewById(R.id.btn_1); btn[1].setOnClickListener(this);
btn[2] = (Button)findViewById(R.id.btn_2); btn[2].setOnClickListener(this);
btn[3] = (Button)findViewById(R.id.btn_3); btn[3].setOnClickListener(this);
btn[4] = (Button)findViewById(R.id.btn_4); btn[4].setOnClickListener(this);
btn[5] = (Button)findViewById(R.id.btn_5); btn[5].setOnClickListener(this);
//----------------------------------------
calc = new Calculator(this); curr = -1;
}
public void show(String tx){ tv.setText(tx); }
public void onClick(View arg0) {
if(arg0 == btn[0]) { calc.EvDigitPress(1); curr = 0; }
else if(arg0== btn[1]) { calc.EvDigitPress(0); curr = 1;}
else if(arg0== btn[2]) { calc.EvCPress(); curr = 2; }
else if(arg0== btn[3]) { calc.EvPlusPress(); curr = 3; }
else if(arg0== btn[4]) { calc.EvAssignPress(); curr = 4; }
else if(arg0== btn[5]) { finish(); }
setting_color();
}
public void setting_color() {
for(int i = 0; i<6; i++ ) {
if(i == curr) btn[i].setTextColor(Color.RED);
else btn[i].setTextColor(Color.BLACK);
}
}}
此ac01对象接到Android送来的OnClick事件,依据所按的按钮而分别转发出不同的讯息(或事件)给Calculator对象,也就调用了Caculator类别,这Calculator类别转而调用NativeJniAdder的calculate()函数。这Calculator.java的程序码如下:
// Calculator.java
package com.misoo.gx05;
public class Calculator {
public int digit_1, digit_2, state_var_A, d;
private ac01 ax;
Calculator(ac01 acx)
{ ax = acx;
this.goto_state_ready();
}
void EvDigitPress(int dg){
this.d = dg;
switch(state_var_A){
case 0: goto_state_first(); break;
case 1: goto_state_first(); break;
case 2: goto_state_second(); break;
case 3: goto_state_second(); break;
}}
void EvPlusPress(){
if(state_var_A == 1)
goto_state_plus();
}
void EvAssignPress(){
if(state_var_A == 3)
goto_state_cal();
}
void EvCPress(){
goto_state_ready();
}
private void goto_state_ready(){
state_var_A = 0; digit_1 = digit_2 = 0; ax.show("><"); }
private void goto_state_first(){
state_var_A = 1;
if(d == 1) ax.show("1");
else ax.show("0");
digit_1 = d;
}
private void goto_state_plus(){ state_var_A = 2; }
private void goto_state_second(){
state_var_A = 3;
if(d == 1) ax.show("1");
else ax.show("0");
digit_2 = d;
}
private void goto_state_cal(){
state_var_A = 4;
int cs = NativeJniAdder.calculate(digit_1, digit_2);
int sum = cs % 10;
int carry = cs / 10;
String carry_sum_str = String.valueOf(carry) + String.valueOf(sum);
ax.show("[" + carry_sum_str +"]");
}}
以上范例里的各类别,皆是使用Java来撰写的,并不需要使用到JNI或NDK。在下一节里,将改用C来撰写Calculator和NativeJniAdder两个类别。
[Go Back]