phonemefeature中功能模块及 KNI 的编写方法
1 目录结构... PAGEREF _Toc325476518 \h1
2 如何添加一个subsystem.. PAGEREF _Toc325476519 \h 2
3 如何编译到KVM中去... PAGEREF _Toc325476520 \h 5
4 如何编写KNI代码... PAGEREF _Toc325476521 \h 6
附录. PAGEREF _Toc325476522 \h7
1.1 midp\src目录下每个文件夹都是一个subsystem,每个文件夹中有一个subsystem.gmk 作为该subsystem 的 makefile。
1.2 Subsystem 文件夹内是各个lib,各子系统的 subsystem.gmk 都要包含本子系统需要的 lib 。
1.3 在相应 lib 目录下,lib.gmk作为本lib的makefile,上层subsystem.gmk需要include该lib.gmk;一般地有3个文件夹,classes、include、native (or reference),分别用于(也许还有i3test,用于java测试代码):
classes: java代码,其中的java接口函数调用C语言实现的native方法;
Include: native中用到的头文件;
Native: C实现的native 代码。
2.1 添加一个subsystem需要的文件一般如下:
src/subsystem.gmk
src/lib.gmk
src/native -- Thiscontains native implementation
src/classes --This contains your java implementation
src/include ---This contains native header files
2.2 一般步骤如下:
step 1: 添加子系统test
step 2: 编写subsystem.gmk
step 3: 添加库test_a
step 4: 在test_a下编写classes\native代码
step 5: 编写lib.gmk
2.3 subsystem.gmk 示例( 其中SUBSYSTEM_DIR = $(MIDP_DIR)/src )
######################################################################
# 2012-05-22 Written byFurtherChan
#
# Module's ComponentConfiguration file
######################################################################
# Add to global SUBSYSTEMSlist
SUBSYSTEM_TEST = test
SUBSYSTEMS +=$(SUBSYSTEM_TEST)
SUBSYSTEM_TEST_DIR =$(SUBSYSTEM_DIR)/test
#####################################################################
# test_a subsystem
# Description:
#####################################################################
include$(SUBSYSTEM_TEST_DIR)/test_a/lib.gmk
#####################################################################
# test_b subsystem
# Description:
#####################################################################
# include$(SUBSYSTEM_TEST_DIR)/test_b/lib.gmk
#####################################################################
# test_c subsystem
# Description:
#####################################################################
# include$(SUBSYSTEM_TEST_DIR)/test_c/lib.gmk
SUBSYSTEM_TEST_JAVA_FILES += $(SUBSYSTEM_TEST_A_JAVA_FILES)
SUBSYSTEM_TEST_NATIVE_FILES += $(SUBSYSTEM_TEST_A_NATIVE_FILES)
#SUBSYSTEM_HIGHUI_EXTRA_INCLUDES += $(SUBSYSTEM_ANNUNCIATOR_EXTRA_INCLUDES)
#SUBSYSTEM_HIGHUI_I3TEST_JAVA_FILES +=$(SUBSYSTEM_ANNUNCIATOR_I3TEST_JAVA_FILES)
2.4 lib.gmk 示例
######################################################################
# 2012-05-22 Written byFurtherChan
#
# TEST_A Library
######################################################################
# Name of the library
TEST_A_NAME = test_a
TEST_A_DIR =$(SUBSYSTEM_TEST_DIR)/$(TEST_A_NAME)
# Add to library set for thisbuild
LIB_SET += $(TEST_A_NAME)
# Export include files
#SUBSYSTEM_LCDLF_EXTRA_INCLUDES += -I$(TEST_A_DIR)/include
# Native files for thelibrary
SUBSYSTEM_TEST_NATIVE_FILES+= HelloWorld_kni.c
# Source code path for thelibrary
vpath % $(TEST_A_DIR)/native
# Java files for the library
#
SUBSYSTEM_TEST_JAVA_FILES += \
$(TEST_A_DIR)/classes/first/second/third/HelloWorld.java
3.1 把自己编写的native和java调用代码编译到KVM中去,需要修改一些makefile,也就是修改编译规则,把添加的代码加入到生成规则中去。在编译过程中可以看到如下信息:
=======================================
MIDPSubsystem and Module Configuration
=======================================
SUBSYSTEMS = configurationconfiguration properties_port example example verifier ams_folders ams_debugon_device_debug jams example core i18n highlevelui lowlevelui rms security derocsp gcf file http serial serial_port socket socket_notify ssocket udp pipepush events tool automation media
SUBSYSTEM_AMS_MODULES = jams
SUBSYSTEM_EVENTS_MODULES = master_mode
……
以上SUBSYSTEMS就是列出的被编译的subsystem。为了编译到SUBSYSTEMS中去,为此需要修改两个文件:
phoneme\midp\build\common\makefiles\Subsystems.gmk
phoneme\midp\build\common\makefiles\SubsystemDefs.gmk
其中前面的Subsystems.gmk 用于include 各个子系统的subsystem.gmk;
后面的SubsystemDefs.gmk 用于子系统lib源文件的添加,即添加lib.gmk中定义的几个变量:SUBSYSTEM_XXX_JAVA_FILES、SUBSYSTEM_XXX_NATIVE_FILES等。
修改完毕后编译,可发现该subsystem已在SUBSYSTEMS中。
对于添加的native文件,在phoneme/output/midp/obj/arm/中可找到对应生成的obj文件;
对于添加的java文件,编译中有preverify .class过程,没有添加的情况下目前有621个。
3.2 Subsystems.gmk 添加示例
#####################################################################
# Test Subsystem
# 2012-05-22 Added byFurtherChan
#####################################################################
# 2012-05-22 Added byFurtherChan
include$(SUBSYSTEM_DIR)/test/$(SUBSYSTEM_MAKE_FILE)
# Added End
3.3 SubsystemDefs.gmk添加示例
#####################################################################
# Test Subsystem
# 2012-05-22 Added byFurtherChan
#####################################################################
# 2012-05-22 Added byFurtherChan
$(MIDP_CLASSES_ZIP)::$(SUBSYSTEM_TEST_JAVA_FILES)
$(appendjavafiles)
JTWI_I3TEST_JAVA_FILES += $(SUBSYSTEM_TEST_I3TEST_JAVA_FILES)
JTWI_NATIVE_FILES +=$(SUBSYSTEM_TEST_NATIVE_FILES)
# Added End
4.1 可用数据类型、参数传递方法、值返回方法等参考kni.h
4.2 C代码native函数命名遵循:Java_pkname1_pkname2_pkname3_classname_methodname(),
如:Java_first_second_third_HelloWorld_sayHello(),则对应的java实现函数在
classes\first\second\third\HelloWorld.java:public native void sayHello();
4.3 示例
midp\src\test\test_a\native\HelloWorld_kni.c:
#include <kni.h>
#include <stdio.h>
KNIEXPORT KNI_RETURNTYPE_VOIDJava_first_second_third_HelloWorld_sayHello()
{
printf("KNITesting\n");
KNI_ReturnVoid();
}
midp\src\test\test_a\classes\first\second\third\HelloWorld.java:
package first.second.third;
import java.lang.*;
public class HelloWorld
{
public native void sayHello();
}
/**
*KNI is an implementation-level native function interface
*for CLDC-category VMs. KNI is intendedto be significantly
*more lightweight than JNI, so we have made some compromises:
*
* -Compile-time interface with static linking.
* -Source-level (no binary level) compatibility.
* -No argument marshalling. All native functions have
* signature void(*)(). Arguments are read explicitly,
* andreturn values are set explicitly.
* -No invocation API (cannot call Java from native code).
* -No class definition support.
* -Limited object allocation support (strings only).
* -Limited array region access for arrays of a primitive type.
* -No monitorenter/monitorexit support.
* -Limited error handling and exception support.
* KNIfunctions do not throw exceptions, but return error
* values/null instead, or go fatal for severe errors.
* -Exceptions can be thrown explicitly, but no direct
* exception manipulation is supported.
*/
======================================================
KNI返回类型:cldc\src\vm\share\natives\kni.h
#define KNI_RETURNTYPE_VOID void
#define KNI_RETURNTYPE_BOOLEAN jint
#define KNI_RETURNTYPE_BYTE jint
#define KNI_RETURNTYPE_CHAR jint
#define KNI_RETURNTYPE_SHORT jint
#define KNI_RETURNTYPE_INT jint
#define KNI_RETURNTYPE_FLOAT JVM_SOFTFP_LINKAGE jfloat
#define KNI_RETURNTYPE_LONG jlong
#define KNI_RETURNTYPE_DOUBLE JVM_SOFTFP_LINKAGE jdouble
#define KNI_RETURNTYPE_OBJECT jobject