JNI本地方法支持java对象的传递。本文就java如何传递对象给C++的DLL,在C++中又如何获取java对象的变量,如何调用java函数以及如何接收java传递的中文字符串问题做一个简单的描述。
假设我们需要传递如下所示对象:
package Editor;
class MyObject
{
int value1;
String value2;
MyObject() { }
MyObject(int v1, String v2)
{
value1 = v1;
value2 = v2;
}
public void setValue(String v2)
{
value2 = v2;
}
}
public class Editor
{
// 定义本地方法,可以是static也可以是非static
public native static int add(int x, int y);
// 定义本地方法,传入一个对象和一个字符串(如何传递中文)
public native static void transferObject(MyObject obj, String inStr);
static
{
// 加载动态链接库,不需要写扩展名,由JVM自动识别
System.loadLibrary("TestDLL");
}
}
在C++中即可按照如下方式实现本地方法:
#include "Editor.h"
#include "Utility.h"
#include "string"
JNIEXPORT jint JNICALL Java_Editor_Editor_add
(JNIEnv *, jclass, jint x, jint y)
{
return x + y;
}
JNIEXPORT void JNICALL Java_Editor_Editor_transferObject
(JNIEnv * pJNIEnv, jclass j, jobject jobj, jstring jsIn)
{
jclass jcls = pJNIEnv->GetObjectClass( jobj );
/**
* 获得变量和方法的定义,其中第三个参数是该变量的类型所对应的标签。
*
* boolean Z
* byte B
* char C
* short S
* int I
* long L
* float F
* double D
* void V
* object L包名/类名;
* Array [数组类型
* method (参数类型)返回类型
*/
jfieldID jfid1 = pJNIEnv->GetFieldID( jcls, "value1", "I" );
jfieldID jfid2 = pJNIEnv->GetFieldID( jcls, "value2", "Ljava/lang/String;");
jmethodID jmid = pJNIEnv->GetMethodID( jcls, "setValue", "(Ljava/lang/String;)V" );
// 获得变量的值
jint value1 = pJNIEnv->GetIntField( jobj, jfid1 );
jstring value2 = ( jstring )pJNIEnv->GetObjectField( jobj, jfid2 );
// 获得字符串,但是下面的函数会对中文输入产生乱码,需要自己手动转换
// char * pcValue2 = pJNIEnv->GetStringUTFChars ( value2, NULL );
char * pcValue2 = JStringToCharArray( pJNIEnv, value2 );
printf( "C++:value1 = %d, value2 = %s ", value1, pcValue2 );
char * pcIn = JStringToCharArray( pJNIEnv, jsIn );
printf( "C++:输入参数(inStr) = %s ", pcIn );
// 修改传入对象的成员变量
pJNIEnv->SetIntField( jobj, jfid1, 5 );
// 调用传入对象的函数修改成员变量
pJNIEnv->CallVoidMethod( jobj, jmid, pJNIEnv->NewStringUTF( "Chinese!" ) );
}
由于java中的中文字符编码为UNICODE,为宽字节字符集,而C++的中文字符编码为ANSII,为多字节字符集,需要对传入的中文参数执行转换。JStringToCharArray函数实现如下:
#include "jni.h"
#include "Windows.h"
char * JStringToCharArray(JNIEnv * pJNIEnv, jstring jstr)
{
jsize len = pJNIEnv->GetStringLength( jstr );
const jchar * jcstr = pJNIEnv->GetStringChars( jstr, NULL );
int size = 0;
char * str = ( char * )malloc( len * 2 + 1 );
if ( (size = WideCharToMultiByte( CP_ACP, 0, LPCWSTR( jcstr ), len, str, len * 2 + 1, NULL, NULL ) ) == 0 )
return NULL;
pJNIEnv->ReleaseStringChars( jstr, jcstr );
str[ size ] = 0;
return str;
}
测试代码:
package Editor;
public class TestEditor
{
public static void main(String[] args)
{
int ret = Editor.add(10, 10);
System.out.println("add(10, 10) = " + ret);
MyObject obj = new MyObject(10, "测试test");
System.out.println("调用DLL前:obj.value1 = " + obj.value1 + ", obj.value2 = " + obj.value2);
Editor.transferObject(obj, "测试test");
System.out.println("调用DLL后:obj.value1 = " + obj.value1 + ", obj.value2 = " + obj.value2);
}
}
运行后输出:
add(10, 10) = 20
调用DLL前:obj.value1 = 10, obj.value2 = 测试test
调用DLL后:obj.value1 = 5, obj.value2 = Chinese!
C++输出:value1 = 10, value2 = 测试test
C++输出:这是一个传入参数(inStr) = 测试test
由此可见,C++不仅能接收java对象、java字符串、也能调用java函数。如果合理的利用JNI,C++还能接收java数组、返回java对象、返回java数组。。。
分享到:
相关推荐
本资料将详细介绍如何在JNI中正确地传递和处理中文字符串。 首先,我们需要理解Java和C/C++对字符串编码的不同处理方式。Java使用UTF-16编码,每个字符占用16位,这使得Java可以轻松处理包括中文在内的多种语言字符...
本篇文章将深入探讨如何在JNI中传递对象数组,包括字符串、整数和小数。 首先,我们需要了解JNI的基本架构。在Java层,我们创建一个本地方法声明,这个方法将被JNI调用。在C/C++层,我们实现这个本地方法,并通过...
`JNI对象的操作.txt`可能会涵盖更多基本对象的创建和访问,而`JNI字符串处理.txt`将详细讲解String对象的各种操作。`jni数据处理.txt`可能涉及不同类型的数据转换,如整型、浮点型和数组的处理。 总的来说,JNI提供...
在本示例中,我们关注的是JNI中的字符串参数传递和返回值处理,这对于那些需要在Java和C/C++之间进行深度集成的项目非常重要。 1. **JNI基本概念** JNI是Java平台提供的一个接口,它使得开发者可以编写本地方法...
可以使用`MultiByteToWideChar`和`WideCharToMultiByte`函数来完成这个转换,确保Java和本地代码之间正确地传递中文字符串。 在DLL中,我们还需要注意线程安全问题。如果多个Java线程同时调用DLL中的函数,可能需要...
然而,处理复杂对象,如字符串、数组或自定义类,需要更多的步骤。对于Java字符串,我们可以使用`env->NewStringUTF`创建一个新的本地字符串,或使用`env->GetStringUTFChars`获取字符串的UTF-8表示。例如: ```c++...
总之,这个"android jni 中文字符传递demo"涵盖了在Android应用中使用JNI处理中文字符的核心技术,这对于那些需要在Java和C/C++之间交换中文数据的开发者来说,是一个非常有价值的参考资料。通过深入学习和实践这个...
在具体实践时,例如我们的示例`JniString3`,可能涉及到Java字符串对象`String`的传递。Java的`String`在JNI中可以转换为`jstring`类型。我们可以使用`GetStringUTFChars`获取字符串的UTF-8编码,或者使用`...
注意,由于Java对象不能直接在JNI中跨线程使用,因此如果要在C/C++中存储或操作Java对象,通常需要将对象序列化为基本类型(如整数或字符串)。对于复杂的对象,可能需要自定义序列化和反序列化逻辑。 5. **内存...
2. 内存管理:由于C++和Java的内存管理机制不同,需要谨慎处理字符串和对象的生命周期,避免内存泄漏。 3. 类型转换:在JNI中,Java对象和本地类型之间需要进行转换,如`jstring`到`std::string`,`jobject`到特定的...
Java的字符串在JNI中表现为`jstring`,可以使用`GetStringUTFChars`获取字符串的UTF-8编码,处理完后用`ReleaseStringUTFChars`释放。如果需要创建Java字符串,可以使用`NewStringUTF`。 5. **内存管理**: JNI中...
在这个示例中,我们将使用JNI来实现Java代码和C++代码之间的对象传递。 在这个示例中,我们定义了一个Java类`WifiManager`,它具有两个native方法:`test()`和`getScanResult()`。`test()`方法返回一个字符串,而`...
- 处理JNI中的字符串、整型数组、字符串数组和对象数组等数据的传递和处理。 - Java程序中JNI的使用涉及到多线程环境下的安全性和同步问题,JNI需要在特定线程中调用,无法跨线程传递对象引用,需要特别注意。 - JNI...
在Android中,当你需要在C/C++代码中创建Java字符串对象时,可以使用JNI提供的函数`NewString`。这个函数接受两个参数:一个`jchar`类型的数组,以及数组的长度。`jchar`是JNI中的一个类型,它对应于Java中的`char`...
本主题聚焦于"Java与C交互传递字符串和整型",这涉及到Java Native Interface (JNI) 和 Android Native Development Kit (NDK) 的使用。 首先,让我们深入了解JNI。JNI是Java平台的标准编程接口,它允许Java代码和...
| `String` | `jstring` | 字符串对象 | | `Object[]` | `jobjectArray` | 任何对象的数组 | | `boolean[]` | `jbooleanArray` | 布尔型数组 | | `byte[]` | `jbyteArray` | 比特型数组 | | `char[]` | `jcharArray`...
在Android开发中,JNI(Java Native Interface)是一种让Java代码调用本地(C/C++)代码的技术,它极大地扩展了Android应用的性能和功能。本示例程序主要讲解如何在Android Studio中通过JNI进行数组的传递,从而实现...
总结起来,Android中的JNI与`jstring`使用涉及到Java与C/C++之间的交互,包括如何获取和释放字符串的UTF-8表示,以及如何在两个环境中安全地传递数据。熟悉这些概念和操作对优化性能、利用原生库和实现特定功能至关...
15.2.2.3 传递字符串... 28 15.2.2.4 传递整型数组... 29 15.2.2.5 传递字符串数组... 30 15.2.2.6 传递对象数组... 31 Chap7:Jni中C++和Java的参数传递... 33 Chap8:如何将java传递过来的jbyteArray转换成C/...
2. 本地字符串到Java字符串:`NewString`用于创建Java字符串对象,`GetStringUTFLength`和`GetStringUTFChars`处理UTF-8编码的字符串。 六、异常处理 1. 检查和抛出异常:JNI提供`ExceptionCheck`检查当前是否有...