JNI之Helloworld

问题背景:由于最近生活轻松,毕设刚刚紧张起来,音频检索的代码全部是C/C++编写的,而B/S平台的应有要搭建服务器,我只会J2EE/JSP那些东东,所以要学会JNI调C/C++代码。

下面介绍下如何构建自己第一个JNI程序。

(1) 将%JAVA_HOME%下的include文件夹的jni.h等等所有的头文件拷贝到VC IDE下面的Include目录下。

(2) 编写Printf.java类

public class Printf {
 
// 导入动态链接库,这个库是用cl.exe或者直接用VC生存的。
static
{
System.loadLibrary("HelloNative3.dll");
}
 
// 最简单的打印“Helloworld”的方法
public native static void greeting();
 
// 传递字符串实验方法
public native static String sprint(String str);
 
}

(3) 编译上面Printf类,在cmd输入 javah Printf。生成了Printf.h头文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Printf */
 
#ifndef _Included_Printf
#define _Included_Printf
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:      Printf
* Method:     greeting
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Printf_greeting
(JNIEnv *, jclass);
 
/*
* Class:      Printf
* Method:     sprint
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Printf_sprint
(JNIEnv *, jclass, jstring);
 
#ifdef __cplusplus
}
#endif
#endif

(4) 打开VC IDE新建DLL工程。

新建HelloNative.cpp,编译如果出现错误尝试把(env *)改为(env) 或者 改文件名为HelloNative.c

#include <stdio.h>
#include "Printf.h"
#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
 
char* jstringToWindows( JNIEnv *env, jstring jstr );
jstring WindowsTojstring( JNIEnv* env, char* str );
 
JNIEXPORT void JNICALL Java_Printf_greeting(JNIEnv * env, jclass cl)
{
printf("hello, Native World!\n");
}
 
char* searchMusic(const char music_path[])
{
char* music_info = "这里显示的是音乐的具体信息,该参数应有其他函数返回";
return music_info;
}
 
JNIEXPORT jstring JNICALL Java_Printf_sprint(JNIEnv * env, jclass cl, jstring j_str)
{
const char* c_str;
char* c_res;
jstring j_res;
 
<strong><em> // 用以下方法中文出现乱码</em>
// c_str = (*env)->GetStringUTFChars(env,j_str,NULL);
c_str = jstringToWindows( env, j_str );</strong>
printf("%s\n",c_str);
c_res = searchMusic(c_str);
<strong> j_res = WindowsTojstring(env ,c_res);</strong>
 
<strong><em> // 用以下方法中文出现乱码</em>
// j_res = (*env)->NewStringUTF(env,c_res);</strong>
(*env)->ReleaseStringUTFChars(env,j_str,c_str);
return j_res;
}
 
// 从Java传递过来的字符串参数转化为C能读懂的中文char
char* jstringToWindows( JNIEnv  *env, jstring jstr )
 
{
 
int length = (*env)->GetStringLength(env,jstr );
 
const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );
 
char* rtn = (char*)malloc( length*2+1 );
 
int size = 0;
 
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
 
if( size <= 0 )
 
return NULL;
 
(*env)->ReleaseStringChars(env,jstr, jcstr );
 
rtn[size] = 0;
 
return rtn;
 
}
 
// C处理返回的字符串转化为中文
 
jstring WindowsTojstring( JNIEnv* env, char* str )
 
{
 
jstring rtn = 0;
 
int slen = strlen(str);
 
unsigned short* buffer = 0;
 
if( slen == 0 )
 
rtn = (*env)->NewStringUTF(env,str );
 
else
 
{
 
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
 
buffer = malloc( length*2 + 1 );
 
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
 
rtn = (*env)->NewString( env, (jchar*)buffer, length );
 
}
 
if( buffer )
 
free( buffer );
 
return rtn;
 
}

(5) 在VC中生成HelloNative.dll 拷贝到System32下面。

(6) 测试Java类

public class HelloNativeTest {
 
public static void main(String[] args) throws Exception {
 
Printf.greeting();
 
String music_utf = Printf.sprint("F:\\中文音乐");
 
System.out.println(  music_utf );
 
}
}

2 Comments on this Post.

  1. hutaow

    好详细!哈哈这个我也做过
    帮着补充个边边角角,那个dll只放在环境变量能搜到的地方都可以,Windows目录,我还曾经放过Java的bin目录里~

  2. admin

    哈哈 这个我还是毕业前作的 记不得了都 总之放很多地方总会找的到的。。。

Leave a Comment.