首页 > 代码库 > JNI点滴

JNI点滴



一、java通过JNI调用DLL
//MyNative.java
public class MyNative{
 static{
   System.loadLibrary("MyNative");
 }
 public native static void HelloWorld();
 public native String cToJava();
}
本地方法(native)是否为静态方法(static),所产生的C函数参加类型是jclass 或jobject.


通过命令javac MyNative.java生成MyNative.class文件;然后javah MyNative生成MyNative.h头文件。
余下的工作交给VC来完成其实现部分。
//MyNative.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyNative */
#ifndef _Included_MyNative
#define _Included_MyNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: MyNative
 * Method: HelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_MyNative_HelloWorld
  (JNIEnv *, jclass);
/*
 * Class: MyNative
 * Method: cToJava
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_MyNative_cToJava
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif


上面两个函数的实现在具体的工程中完成,通过创建DLL工程,新建MyNative.cpp文件,
//MyNative.cpp工程属性设置包含JDK目录中include子目录
#include <stdio.h>
#include "MyNative.h"
JNIEXPORT void JNICALL Java_MyNative_HelloWorld
 (JNIEnv *, jclass){
  printf("Hello World 你好中国");
}
JNIEXPORT jstring JNICALL Java_MyNative_cToJava
 (JNIEnv *env, jobject obj){
  jstring jstr;
  char str[]="Hello 美国\n";
  jstr=env->NewStringUTF(str);
  return jstr;
}


测试所写的DLL文件所用java类:
public class mytest{
 public static void main(String args[]){
 MyNative a= new MyNative();
 a.HelloWorld();
 System.out.println(a.cToJava());
  }
}
假如jni.h头文件没有修改,上述a.cToJava()方法打印出的信息会出现乱码。
即“美国”出现乱码,修改NewStringUTF方法。  


下面具体分析jni.h头文件涉及的函数及知识点
    const jchar *GetStringChars(jstring str, jboolean *isCopy) {
        return functions->GetStringChars(this,str,isCopy);
    }
返回 Unicode字符串,类型jchar占用2字节。

NewStringUTF根据Native的一个UTF-8字符串得到一个Jstring对象,

修改NewStringUTF方法如下:
jstring NewStringUTF(const char *utf) {
  jstring rtn = 0;
  int slen = strlen(utf);
  unsigned short * buffer = 0;
  if( slen == 0 )
  rtn = functions->NewStringUTF(this,utf );
  else
  {
  int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)utf, slen, NULL, 0 );
  buffer = (unsigned short *)malloc( length*2 + 1 );
  if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)utf, slen, (LPWSTR)buffer, length ) >0 )
  rtn = functions->NewString(this,(jchar*)buffer, length );
  }
  if( buffer )
      free( buffer );
  return rtn;
        //return functions->NewStringUTF(this,utf);
}

[多字节与宽字节转换]
MultiByteToWideChar function
Maps a character string to a UTF-16 (wide character) string.  
int MultiByteToWideChar(
  _In_       UINT CodePage,
  _In_       DWORD dwFlags,
  _In_       LPCSTR lpMultiByteStr,
  _In_       int cbMultiByte,
  _Out_opt_  LPWSTR lpWideCharStr,
  _In_       int cchWideChar
);
代码页由CP_ACP和CP_UTF8
//ANSI to Unicode 
 wstring ANSIToUnicode( const string& str )
{
 int len = 0;
 len = str.length();
 int unicodeLen = ::MultiByteToWideChar( CP_ACP,0,str.c_str(),-1,NULL,0 );
 wchar_t * pUnicode;
 pUnicode = new wchar_t[unicodeLen+1];
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
 ::MultiByteToWideChar( CP_ACP,0,str.c_str(),-1,(LPWSTR)pUnicode,unicodeLen );
 wstring rt;
 rt = ( wchar_t* )pUnicode;
 delete pUnicode;
 return rt;
}

//Unicode to ANSI
string UnicodeToANSI( const wstring& str )
{
 char* pElementText;
 int iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_ACP,
  0,
  str.c_str(),
  -1,
  NULL,
  0,
  NULL,
  NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_ACP,
  0,
  str.c_str(),
  -1,
  pElementText,
  iTextLen,
  NULL,
  NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;
}
//UTF-8 to Unicode
wstring UTF8ToUnicode( const string& str )
{
 int len = 0;
 len = str.length();
 int unicodeLen = ::MultiByteToWideChar( CP_UTF8,0,str.c_str(),-1,NULL,0 );
 wchar_t * pUnicode;
 pUnicode = new wchar_t[unicodeLen+1];
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
 ::MultiByteToWideChar( CP_UTF8,0,str.c_str(),-1,(LPWSTR)pUnicode,unicodeLen );
 wstring rt;
 rt = ( wchar_t* )pUnicode;
 delete pUnicode;
 return rt;
}

//Unicode to UTF-8   
string UnicodeToUTF8( const wstring& str )
{
 char* pElementText;
 int iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_UTF8,0,str.c_str(),-1,NULL,0,NULL,NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_UTF8,0,str.c_str(),-1,pElementText,iTextLen,NULL,NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;
}


一、java通过JNI调用DLL
//MyNative.java
public class MyNative{
 static{
   System.loadLibrary("MyNative");
 }
 public native static void HelloWorld();
 public native String cToJava();
}
本地方法(native)是否为静态方法(static),所产生的C函数参加类型是jclass 或jobject.


通过命令javac MyNative.java生成MyNative.class文件;然后javah MyNative生成MyNative.h头文件。
余下的工作交给VC来完成其实现部分。
//MyNative.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyNative */
#ifndef _Included_MyNative
#define _Included_MyNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: MyNative
 * Method: HelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_MyNative_HelloWorld
  (JNIEnv *, jclass);
/*
 * Class: MyNative
 * Method: cToJava
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_MyNative_cToJava
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif


上面两个函数的实现在具体的工程中完成,通过创建DLL工程,新建MyNative.cpp文件,
//MyNative.cpp工程属性设置包含JDK目录中include子目录
#include <stdio.h>
#include "MyNative.h"
JNIEXPORT void JNICALL Java_MyNative_HelloWorld
 (JNIEnv *, jclass){
  printf("Hello World 你好中国");
}
JNIEXPORT jstring JNICALL Java_MyNative_cToJava
 (JNIEnv *env, jobject obj){
  jstring jstr;
  char str[]="Hello 美国\n";
  jstr=env->NewStringUTF(str);
  return jstr;
}


测试所写的DLL文件所用java类:
public class mytest{
 public static void main(String args[]){
 MyNative a= new MyNative();
 a.HelloWorld();
 System.out.println(a.cToJava());
  }
}
假如jni.h头文件没有修改,上述a.cToJava()方法打印出的信息会出现乱码。
即“美国”出现乱码,修改NewStringUTF方法。  


下面具体分析jni.h头文件涉及的函数及知识点
    const jchar *GetStringChars(jstring str, jboolean *isCopy) {
        return functions->GetStringChars(this,str,isCopy);
    }
返回 Unicode字符串,类型jchar占用2字节。

NewStringUTF根据Native的一个UTF-8字符串得到一个Jstring对象,

修改NewStringUTF方法如下:
jstring NewStringUTF(const char *utf) {
  jstring rtn = 0;
  int slen = strlen(utf);
  unsigned short * buffer = 0;
  if( slen == 0 )
  rtn = functions->NewStringUTF(this,utf );
  else
  {
  int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)utf, slen, NULL, 0 );
  buffer = (unsigned short *)malloc( length*2 + 1 );
  if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)utf, slen, (LPWSTR)buffer, length ) >0 )
  rtn = functions->NewString(this,(jchar*)buffer, length );
  }
  if( buffer )
      free( buffer );
  return rtn;
        //return functions->NewStringUTF(this,utf);
}

[多字节与宽字节转换]
MultiByteToWideChar function
Maps a character string to a UTF-16 (wide character) string.  
int MultiByteToWideChar(
  _In_       UINT CodePage,
  _In_       DWORD dwFlags,
  _In_       LPCSTR lpMultiByteStr,
  _In_       int cbMultiByte,
  _Out_opt_  LPWSTR lpWideCharStr,
  _In_       int cchWideChar
);
代码页由CP_ACP和CP_UTF8
//ANSI to Unicode 
 wstring ANSIToUnicode( const string& str )
{
 int len = 0;
 len = str.length();
 int unicodeLen = ::MultiByteToWideChar( CP_ACP,0,str.c_str(),-1,NULL,0 );
 wchar_t * pUnicode;
 pUnicode = new wchar_t[unicodeLen+1];
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
 ::MultiByteToWideChar( CP_ACP,0,str.c_str(),-1,(LPWSTR)pUnicode,unicodeLen );
 wstring rt;
 rt = ( wchar_t* )pUnicode;
 delete pUnicode;
 return rt;
}

//Unicode to ANSI
string UnicodeToANSI( const wstring& str )
{
 char* pElementText;
 int iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_ACP,
  0,
  str.c_str(),
  -1,
  NULL,
  0,
  NULL,
  NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_ACP,
  0,
  str.c_str(),
  -1,
  pElementText,
  iTextLen,
  NULL,
  NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;
}
//UTF-8 to Unicode
wstring UTF8ToUnicode( const string& str )
{
 int len = 0;
 len = str.length();
 int unicodeLen = ::MultiByteToWideChar( CP_UTF8,0,str.c_str(),-1,NULL,0 );
 wchar_t * pUnicode;
 pUnicode = new wchar_t[unicodeLen+1];
 memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
 ::MultiByteToWideChar( CP_UTF8,0,str.c_str(),-1,(LPWSTR)pUnicode,unicodeLen );
 wstring rt;
 rt = ( wchar_t* )pUnicode;
 delete pUnicode;
 return rt;
}

//Unicode to UTF-8   
string UnicodeToUTF8( const wstring& str )
{
 char* pElementText;
 int iTextLen;
 // wide char to multi char
 iTextLen = WideCharToMultiByte( CP_UTF8,0,str.c_str(),-1,NULL,0,NULL,NULL );
 pElementText = new char[iTextLen + 1];
 memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
 ::WideCharToMultiByte( CP_UTF8,0,str.c_str(),-1,pElementText,iTextLen,NULL,NULL );
 string strText;
 strText = pElementText;
 delete[] pElementText;
 return strText;
}


JNI点滴