`

jni参数的转换

 
阅读更多
1、java 向c传递基本数据类型

对于基本数据类型,java和c是相互对应的,所以可以直接使用。它们的对应关系为;

------------------------------------------------------------------------

Java类型      本地类型   字节(bit)

-------------------------------------------------------------------------
  
  boolean   jboolean   8, unsigned
  byte    jbyte     8
  char    jchar    16, unsigned
  short    jshort    16
  int     jint     32
  long    jlong    64
  float    jfloat    32
  double   jdouble   64
  void    void     n/a

------------------------------------------------------------------------

2.java向c传递对象类型

对于java传递进来的java对象模型,c要加载java类的原型,根据创建相应的c对象,获取java对象的方法的id,然后调用java对象的方法。举例说明:比如有个java类customer对象作为jni参数传递到c程序,customer有方法String getName()。

JNIEXPORT jobject JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomer
(JNIEnv *env, jobject,  jobject customer){

jmethodID methodId;
//获得customer对象的句柄
    jclass cls_objClass=env->GetObjectClass(customer);
//获得customer对象中特定方法getName的id
methodId=env->GetMethodID(cls_objClass,"getName","()Ljava/lang/String;");
//调用customer对象的特定方法getName
jstring  js_name=(jstring)env->CallObjectMethod(customer,methodId,NULL);

...

}

3.c向java返回对象类型

在c程序中首先要创建要返回的java对象,得到每个属性的id,然后给每个属性赋值,最后返回。举例说明:同样是customer对象,有name等属性值,需要在c程序中给每个属性赋值后返回。

JNIEXPORT jobject JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomer
(JNIEnv *env, jobject,  jobject customer){

......

//发现java Customer类,如果失败,程序返回
jclass   clazz = env->FindClass("com/oracle/estt/sc/busi/Customer");  
if(clazz == 0) 
  return   0;   
//为新的java类对象obj分配内存   
jobject   obj = env->AllocObject(clazz);    
//发现类中的属性,如果失败,程序返回  
jfieldID   fid_id = env->GetFieldID(clazz,"customerID","I"); 
if (fid_id  ==  0) 
  return   0;
jfieldID   fid_name = env->GetFieldID(clazz,"name","Ljava/lang/String;"); 
if (fid_name  ==  0) 
  return   0;
......

env->SetIntField(obj, fid_id, 1
env->SetObjectField(obj, fid_name, jname);

......

return obj;

}

4.c向java传递一个含有java对象的数组

对于这种情况,先得到数组的大小,接下来取出数组中的对象,取得对象的属性值或者调用对象的方法,将获得值存到本地数组中,然后可以灵活使用这些数据了。举例说明:java向c传递一个含有多个customer对象的数组,在c中将这个数组的分解出来,存到本地的临时数组中去。

JNIEXPORT void JNICALL Java_com_oracle_estt_sc_db_impl_SCInsertODBC__1insertCustomeRequest___3Lcom_oracle_estt_sc_busi_CustomerRequest_2
(JNIEnv *env, jobject, jobjectArray oa){

......

//声明customerrequest对象
jobject o_customer;

int i;
jmethodID methodId;
jint size=env->GetArrayLength(oa);

_tmp_bind[0]= (char *)malloc(size*sizeof(int));
_tmp_bind[1]= (char *)malloc(size*sizeof(char)*( 20 + 1));

...

//将输入数组的数据拷贝到临时数组中去
for(i=0;i<size;i++){
//从数组中获得customerrequest对象
    o_request=env->GetObjectArrayElement(oa,i);
//获得customerrequest对象的句柄
jclass cls_objClass=env->GetObjectClass(o_request);

//获得customerrequest对象的特定方法getCustomerID的id
methodId=env->GetMethodID(cls_objClass,"getCustomerID","()I");
//调用customerrequest对象的特定方法getCustomerID
int_customerID=env->CallIntMethod(o_request,methodId,NULL);
//获得customerrequest对象中特定方法getTelNum的id
methodId=env->GetMethodID(cls_objClass,"getTelNum","()Ljava/lang/String;");
//调用customerrequest对象的特定方法getTelNum
str_telNum=(jstring)env->CallObjectMethod(o_request,methodId,NULL);

...

//将用户id拷贝到临时数组
memcpy(_tmp_bind[0]+i*sizeof(int),&int_customerID,sizeof(int));

//将电话号码拷贝到临时数组,如果电话号码字符串超长,报错返回
if(sizeof(char)*strlen(chr_tel)<=sizeof(char)*( 20 + 1)){
memcpy(_tmp_bind[1]+i*sizeof(char)*( 20+1 ),chr_tel,strlen(chr_tel)+1);
}else{
printf("%s too long!\n",chr_tel);
return;
}

...

}

...

}

5.c向java返回一个数组

先创建数组,然后加载java对象,给每个java对象的属性赋值,添加到数组中,最后返回数组。如下例:

JNIEXPORT jobjectArray JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomerRequest
(JNIEnv *env, jobject, jint customerid){

......

//声明存放查询结果的objectarray
jobjectArray jo_array = env->NewObjectArray(MAX_LINE,env->FindClass("com/oracle/estt/sc/busi/CustomerRequest"), 0);  jobject obj;
//发现java Customerrequest类,如果失败,程序返回
jclass   clazz = env->FindClass("com/oracle/estt/sc/busi/CustomerRequest");  
if(clazz == 0) 
  return   0;

while ((rc = SQLFetch(hstmt)) == SQL_SUCCESS ||rc == SQL_SUCCESS_WITH_INFO) {

obj = env->AllocObject(clazz);

jfieldID   fid_customerID = env->GetFieldID(clazz,"customerID","I"); 
  if (fid_customerID  ==  0) 
   return   0;

jfieldID   fid_priority = env->GetFieldID(clazz,"priority","I"); 
  if (fid_priority  ==  0) 
   return   0;

...

env->SetIntField(obj, fid_customerID, col_customerID);

env->SetIntField(obj, fid_priority, col_priority);

...

//将对象obj添加到object array中
  if(j<MAX_LINE){
   env->SetObjectArrayElement(jo_array, j, obj);
  }else{
   break;
  }

}

return jo_array;

}

6.jstring向char* 的转换

jstring不能直接在c程序中使用,需要转换成char*。重要的一点是,在使用完char*之后,一定要记得将其释放,以免发生内存泄漏。如下例:

JNIEXPORT jobjectArray JNICALL Java_com_oracle_estt_sc_db_impl_SCQueryODBC__1getCustomerRequestByCondition
(JNIEnv *env, jobject, jstring condition, jint customerid){

//将jstring转换为cha*
char* str_condition=(char*) env->GetStringUTFChars(condition,JNI_FALSE);

......

//释放变量
env->ReleaseStringUTFChars(condition,str_condition);

......

}

7.char*转换成jstring

这个转换就比较麻烦了,但是在数据库操作时会用到。比如,从数据库查询得到的是char*,但是给对象属性赋值的时候需要用jstring,这是需要用到这种转换。具体如下例:

char* col_timestamp=.....;

//加载string类
jclass strClass = env->FindClass("Ljava/lang/String;");
//获得方法id
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");

//将字符串转换为jstring 
  bytes_time = env->NewByteArray(strlen(col_timestamp));
  env->SetByteArrayRegion(bytes_time, 0, strlen(col_timestamp), (jbyte*)col_timestamp);
  jstring js_time = env->NewStringUTF("utf-8");

js_time=(jstring)env->NewObject(strClass, ctorID, bytes_time, js_time)

8.java类的原型获取方法

在c中创建java对象和调用java对象方法时需要用到java类的原型,特别是其方法签名。具体办法是:到java类所在的目录下,键入名命令:

>javap -s -p 包路径.java类名

分享到:
评论

相关推荐

    jni参数详解

    今天,我们将讨论JNI参数的详解,了解JNI参数的含义和使用方法。 一、JNI参数的基本概念 JNI参数是native代码中使用的参数类型,它们是Java类型到C/C++类型的映射关系。JNI参数可以分为基本类型和复杂类型两种。...

    jni数据类型转换

    #### String参数的转换 在JNI环境中,处理Java的`String`类型尤其需要注意,因为其在C/C++中表现为`char*`形式。 1. **从Java到C/C++**: 当Java传递一个`String`至C/C++时,首先会转换为`jstring`。若需进一步...

    通过Jcom调用JNI将Office文档转换Pdf

    本主题聚焦于使用Jcom调用JNI技术来实现这一转换。以下是对这个过程的详细解析: 首先,理解几个核心概念: 1. **Jcom**:Jcom是一款Java组件,它提供了对COM组件(Component Object Model)的访问能力。COM是微软...

    android NDK 自动生成jni头文件

    其中,[options] 是可选参数,&lt;classes&gt; 是要转换的 Java 类文件的名称。 javah 命令提供了多种选项,包括: * -help:显示帮助信息 * -classpath &lt;path&gt;:指定类文件的搜索路径 * -bootclasspath &lt;path&gt;:指定...

    JNI 调 C C++ 参数String

    在标题“JNI 调 C/C++ 参数String”中,我们将探讨如何通过JNI传递Java的String类型参数到C或C++函数,并在本地代码中进行处理。 首先,让我们了解JNI的基本结构。要使用JNI,你需要创建一个Java类,声明一些 ...

    Jni中C++和Java的参数传递

    在C++中,我们可以使用`jobject`或`jclass`来表示Java对象,通过JNI函数进行参数转换。 传递`DiskInfo`结构体到Java中,我们首先需要在Java中定义对应的类,然后在C++中实现本地方法来处理这些参数。使用`javah`...

    开发JNI程序的工具集

    这个文件会详细列出所有可用的JNI函数,包括它们的参数、返回值以及用途。开发者可以通过查阅这个文件,了解如何声明和使用本地方法,如何初始化Java虚拟机(JVM),如何调用Java对象的方法和访问其字段,以及如何...

    JNI中C和Java参数传递详细例子

    ### JNI中C和Java参数传递详解 #### 一、引言 Java Native Interface (JNI) 是Java平台标准的一部分,用于让Java代码与其他语言写的代码进行交互。本文将深入探讨在JNI环境中,C/C++和Java之间如何进行参数传递,...

    Android调用Jni返回自定义对象

    然后,你需要在JNI中定义一个函数,接收Java对象作为参数,处理后返回自定义对象。这通常涉及到JNI的`NewObject`函数,用于创建Java对象。例如: ```cpp jobject createCustomObject(JNIEnv *env, int id, const ...

    JNI

    首先,本地方法的参数和返回值都需要转换为JNI数据类型,如`jint`, `jobject`等。其次,线程安全是个挑战,因为Java的多线程机制和C/C++的多线程处理方式不同,需要谨慎管理线程同步。最后,性能优化是另一个重要...

    C++库封装JNI接口-实现java调用c++

    在跨平台的软件开发中,有时我们需要...这个过程需要理解Java和C++之间的数据类型转换,以及如何在两种语言之间传递参数和返回值。熟练掌握JNI可以极大地扩展Java应用的功能,尤其是在需要高性能计算或利用硬件特性时。

    jniDemo简单版

    `JNIEnv *env`参数是JNI环境指针,用于调用JNI接口。`jobject`参数代表Java对象,但在这里我们没有用到,所以用`/* this */`注释掉。 编译C/C++代码,我们可以使用NDK的`ndk-build`命令,或者使用Android Studio的...

    jni实现图片格式转换实例

    我们首先使用JNI的`GetStringUTFChars`获取Java字符串的UTF-8表示,然后使用OpenCV的`imread`函数读取图片,如果图片读取成功,再用`imwrite`写入转换后的图片,这里以转换为PNG为例,通过设置`IMWRITE_PNG_...

    JNI接口开发

    Java方法调用本地方法时,需要将Java中的参数转换为JNI支持的类型: - **基础类型**:如int转换为`jint`,long转换为`jlong`等。 - **String**:转换为`jstring`。 - **其他类型**:包括数组和其他Java对象,统一...

    jni操作arraylist对象

    3. **创建int类型的Java对象**:由于ArrayList的`add`方法期望一个Object参数,我们需要将int值转换为Integer对象。为此,我们需要使用`env-&gt;NewObject`方法创建一个Integer对象。 ```c++ jclass integerClass = ...

    JNI完全技术手册 带完整书签

    Chap7:Jni中C++和Java的参数传递... 33 Chap8:如何将java传递过来的jbyteArray转换成C/C++中的BYTE数组... 47 Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能... 47 Chap9:如何编写jni方法(转载...

    jni.h文件,完美适配ida软件,直接就可以使用。

    4. **数据类型转换**:JNI提供了一系列函数,如`jobjectToHandle`、`GetXXXField`和`SetXXXField`,用于在Java对象和本地数据类型之间进行转换。 5. **异常处理**:JNI允许本地代码抛出和捕获Java异常,通过`Throw`...

    JNI完全技术手册

    4. **处理数据类型**:JNI支持Java和C/C++之间的数据类型转换。例如,Java的`int`在JNI中对应`jint`,`String`对应`jstring`,对象则对应`jobject`。开发者需要了解这些映射关系,以便正确地传递参数和返回值。 5. ...

    android jni 传递对象的demo

    因此,当我们想要在JNI中传递Java对象时,我们需要将对象转换为C/C++可以理解的数据类型,通常是通过序列化或使用JNI提供的特殊机制。 在"HelloWorld"这个简单的例子中,我们可能看到了以下步骤: 1. **定义Java类...

Global site tag (gtag.js) - Google Analytics