天天看點

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);

 * method: ctojava

 * signature: ()ljava/lang/string;

jniexport jstring jnicall java_mynative_ctojava

  (jnienv *, jobject);

上面兩個函數的實作在具體的工程中完成,通過建立dll工程,建立mynative.cpp檔案,

//mynative.cpp工程屬性設定包含jdk目錄中include子目錄

#include <stdio.h>

#include "mynative.h"

 (jnienv *, jclass){

  printf("hello world 你好中國");

 (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對象,

JNI點滴

修改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.  

代碼頁由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,

  null );

 pelementtext = new char[itextlen + 1];

 memset( ( void* )pelementtext, 0, sizeof( char ) * ( itextlen + 1 ) );

 ::widechartomultibyte( cp_acp,

  pelementtext,

  itextlen,

 string strtext;

 strtext = pelementtext;

 delete[] pelementtext;

 return strtext;

//utf-8 to unicode

wstring utf8tounicode( const string& str )

 int unicodelen = ::multibytetowidechar( cp_utf8,0,str.c_str(),-1,null,0 );

 wchar_t * punicode;

 ::multibytetowidechar( cp_utf8,0,str.c_str(),-1,(lpwstr)punicode,unicodelen );

//unicode to utf-8   

string unicodetoutf8( const wstring& str )

 itextlen = widechartomultibyte( cp_utf8,0,str.c_str(),-1,null,0,null,null );

 ::widechartomultibyte( cp_utf8,0,str.c_str(),-1,pelementtext,itextlen,null,null );

JNI點滴
JNI

繼續閱讀