一、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對象,
修改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 );