在JNI中如何将jobject类型转换为jdouble类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在JNI中如何将jobject类型转换为jdouble类型相关的知识,希望对你有一定的参考价值。

此处为Java调用C,C的开发在VS2013中,将jobject类型强制转换为jint、jlong、jstring类型时都可以,但是当强制转换为jdouble和jfloat类型时就报错,这到底是为什么?应该怎么解决?

#include <jni.h>   
#include "com_test_Test.h"  
#include <stdio.h>   
#include <stdlib.h>   
#include <strings.h>   
  
//获取字符串   
JNIEXPORT void JNICALL Java_com_test_Test_sayHello(JNIEnv * env, jobject obj,   
  jstring s)    
  
 char * str = (char *) (*env)->GetStringUTFChars(env, s, 0);   
 printf("\\n c-string: hello - %s", str);   
  
   
  
//获取,返回int   
JNIEXPORT jint JNICALL Java_com_test_Test_add(JNIEnv * env, jobject obj,   
  jint a, jint b)    
 int i = a;   
 int j = b;   
 printf("\\n c-int: %d - %d", i, j);   
 char str[256];   
 sprintf(str, "%d", i + j);   
 return (jint) i + j;   
   
  
//获取,返回float   
JNIEXPORT jfloat JNICALL Java_com_test_Test_getFloat(JNIEnv * env, jobject obj,   
  jfloat f)    
 float fl = f;   
 printf("\\n c-float: %3f", fl);   
  
 fl = 200.555;   
 return (jfloat) fl;   
   
  
//获取,返回 double   
JNIEXPORT jdouble JNICALL Java_com_test_Test_getDouble(JNIEnv * env,   
  jobject obj, jdouble dou)    
 double d = dou;   
 printf("\\n c-double: %3f", d);   
  
 d = 800.88;   
 return (jdouble) d;   
   
  
//获取,返回boolean   
JNIEXPORT jboolean JNICALL Java_com_test_Test_getBoolean(JNIEnv * env,   
  jobject obj, jboolean bool)    
  
 unsigned char b = bool;   
 printf("\\n c-boolean: %lu  ", b);   
 if (b)    
  printf("true");   
  else    
  printf("false");   
    
  
 b = 1;   
 return (jboolean) b;   
   
  
//获取,返回 string   
JNIEXPORT jstring JNICALL Java_com_test_Test_getString(JNIEnv * env,   
  jobject obj, jstring s)    
 char * st = (char *) (*env)->GetStringUTFChars(env, s, 0);   
 printf("\\n c-string:  %s", st);   
  
 char * str = "hello wang wu!";   
 jstring rtn;   
 rtn = (*env)->NewStringUTF(env, str);   
 return rtn;   
   
  
//获取,返回 string []   
JNIEXPORT jobjectArray JNICALL Java_com_test_Test_getStringArray(JNIEnv * env,   
  jobject obj, jobjectArray arr)    
 int len = (*env)->GetArrayLength(env, arr);   
 printf("\\n c-stringArray :");   
 int i = 0;   
 for (i = 0; i < len; i++)    
  jobject obj = (*env)->GetObjectArrayElement(env, arr, i);   
  jstring str = (jstring) obj;   
  const char * szStr = (*env)->GetStringUTFChars(env, str, 0);   
  printf(" %d-%s ", i, szStr);   
  (*env)->ReleaseStringChars(env, str, szStr);   
    
 //-----返回----   
  
 jstring str;   
 jobjectArray args = 0;   
 jsize size = 5;   
 char* sa[] =  "Hello,", "world!", "zhang", "san", "yuang" ;   
 int j = 0;   
 jclass objClass = (*env)->FindClass(env, "java/lang/String");   
 args = (*env)->NewObjectArray(env, size, objClass, 0);   
 for (j = 0; j < size; j++)    
  str = (*env)->NewStringUTF(env, sa[j]);   
  (*env)->SetObjectArrayElement(env, args, j, str);   
    
 return args;   
   
  
-----------------------------------------------------------------   
  
下面是Test.java   
  
package com.test;   
  
public class Test    
 private native void sayHello(String str);   
  
 private native int add(int a, int b);   
  
 private native float getFloat(float f);   
  
 private native double getDouble(double d);   
  
 private native boolean getBoolean(boolean b);   
  
 private native String getString(String str);   
  
 private native String[] getStringArray(String[] sa);   
  
 static    
  System.loadLibrary("Test");   
    
  
 public static void main(String[] args)    
  Test test = new Test();   
  test.sayHello("zhang san");   
  System.out.println("int     --> " + test.add(10, 20));   
  System.out.println("float   --> " + test.getFloat((float) 20.123));   
  System.out.println("double  --> " + test.getDouble(100.369));   
  System.out.println("boolean --> " + test.getBoolean(true));   
  System.out.println("string  --> " + test.getString("wang Wu"));   
  
  String[] ss =  "hello", "-", "zhang", "san" ;   
  Object[] obj = test.getStringArray(ss);   
  System.out.print("string[]-->  ");   
  for (Object object : obj)    
   System.out.print(object + " ");   
     
  
    
  
追问

jdouble作为参数类型直接传可以用,但是我那要从一个传入的Java自定义对象中解析出jdouble类型的数据,就不行。

参考技术A JNIEXPORT jfloat JNICALL Java_com_test_Test_getFloat(JNIEnv * env, jobject obj,

jfloat f)

float fl = f

Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

转自:   http://blog.csdn.net/jiangwei0910410003/article/details/17465457  

上一篇说的是一个简单的应用,说明JNI是怎么工作的,这一篇主要来说一下,那个本地方法sayHello的参数的说明,以及其中方法的使用

首先来看一下C++中的sayHello方法的实现:

 

  1. JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_sayHello (JNIEnv * env, jobject obj)  
  2. {  
  3. cout<<"Hello World"<<endl;  
  4. }  

对于这个方法参数中的JNIEnv* env参数的解释:

JNIEnv类型实际上代表了Java环境,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。例如,创建Jaa类中俄对象,调用Java对象的方法,获取Java对象中的属性等等。JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码进行操作。

JNIEnv类中有很多函数可以用:

NewObject:创建Java类中的对象

NewString:创建Java类中的String对象

New<Type>Array:创建类型为Type的数组对象

Get<Type>Field:获取类型为Type的字段

Set<Type>Field:设置类型为Type的字段的值

GetStatic<Type>Field:获取类型为Type的static的字段

SetStatic<Type>Field:设置类型为Type的static的字段的值

Call<Type>Method:调用返回类型为Type的方法

CallStatic<Type>Method:调用返回值类型为Type的static方法

等许多的函数,具体的可以查看jni.h文件中的函数名称。


参数:jobject obj的解释:

如果native方法不是static的话,这个obj就代表这个native方法的类实例

如果native方法是static的话,这个obj就代表这个native方法的类的class对象实例(static方法不需要类实例的,所以就代表这个类的class对象)


下面来看一下Java和C++中的基本类型的映射关系:

技术分享

具体的说明可以查看jni.h文件。


为了能够在C/C++中使用Java类,jni.h头文件中专门定义了jclass类型来表示Java中的Class类

JNIEnv类中有如下几个简单的函数可以取得jclass:

jclass FindClass(const char* clsName):通过类的名称(类的全名,这时候包名不是用.号,而是用/来区分的)来获取jclass

如: jclass str = env->FindClass("java/lang/String");获取Java中的String对象的class对象。

jclass GetObjectClass(jobject obj):通过对象实例来获取jclass,相当于java中的getClass方法

jclass GetSuperClass(jclass obj):通过jclass可以获取其父类的jclass对象


在C/C++本地代码中访问Java端的代码,一个常见的应用就是获取类的属性和调用类的方法,为了在C/C++中表示属性和方法,JNI在jni.h头文件中定义了jfieldId,jmethodID类型来分别代表Java端的属性和方法

我们在访问,或者设置Java属性的时候,首先就要先在本地代码取得代表该Java属性的jfieldID,然后才能在本地代码中进行Java属性操作,同样的,我们需要呼叫Java端的方法时,也是需要取得代表该方法的jmethodID才能进行Java方法调用


使用JNIEnv的:

GetFieldID/GetMethodID

GetStaticFieldID/GetStaticMethodID

来取得相应的jfieldID和jmethodID

下面来具体看一下这几个方法:

GetFieldID(jclass clazz,const char* name,const char* sign)

方法的参数说明:

clazz:这个简单就是这个方法依赖的类对象的class对象

name:这个是这个字段的名称

sign:这个是这个字段的签名(我们知道每个变量,每个方法都是有签名的)

怎么查看类中的字段和方法的签名:

使用javap命令:

技术分享

GetMethodID也能够取得构造函数的jmethodID,创建一个Java对象时可以调用指定的构造方法,这个将在后面向大家介绍:

如:env->GetMethodID(data_Class,"<init>","()V");

下面看一下签名的格式:

技术分享

下面来看一下例子:

这里没有上代码了:真正演示的时候等下一篇内容,这一篇只是说一下方法的使用:

技术分享

技术分享

下一篇我们将来说一下这些方法到底是怎么用的。











以上是关于在JNI中如何将jobject类型转换为jdouble类型的主要内容,如果未能解决你的问题,请参考以下文章

Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

无法将类型'Newtonsoft.Json.Linq.JObject'的对象转换为类型

如何返回矢量 来自jni C ++函数?

无法将类型为“Newtonsoft.Json.Linq.JObject”的对象转换为类型“System.Collections.Generic.Dictionary`2[System.String,S

android jni介绍

如何调用传递给JNI`jobject`的Java对象的子类/子类的方法