日期:2014-05-16  浏览次数:20605 次

window下jni调用dll和linux下jni调用so库
最近的项目涉及到了JAVA需要调用C程序的问题。主要是调用C写的加密算法。
主要解决方案是应用JNI去调用C生成的so库
用eclispe新建一个java project项目,项目名称为spidHandle,注意下面VC的项目名称也是spidHandle,他们分别是用eclispe和VC6.0创建的,不是同个项目。
编写一个JNI入口类SpidHandle.java:
package com.spidHandle.api;
public class SpidHandle {
		static {
				System.loadLibrary("spidhandle");
		}
		
		public String buildSpID(String path, String login_name, String password, String key)
		{
			return getSPID(path, login_name, password, key);
		}
		
		public native String getSPID(String path, String login_name, String password, String key);

	/**
	 * @param args
	 * 
	 * 供测试用
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String keyforMD5 = "A6EIo8tuaKS";
        String s = new SpidHandle().buildSpID("/test", "test", "test", keyforMD5);
        System.out.println(s);
	}

}


通过CMD命令窗口,CMD命令窗口定位到SpidHandle.java的目录下,编译SpidHandle.java文件:
javac SpidHandle.java

执行JAVAC命令后,在同个文件目录下生成SpidHandle.class
将CMD窗口退回到包的根目录下,如spidHandle工程路径为:
Z:\project\work_workspace\spidhandle
其中通过编译后的SpidHandle.class存在于目录下:
Z:\project\work_workspace\spidhandle\src\com\spidHandle\api
由于SpidHandle类所在的包是com.spidHandle.api,所以CMD命令窗口要退回到Z:\project\work_workspace\spidhandle\src目录
然后在CMD窗口中执行
javah com.spidHandle.api.SpidHandle

执行后在Z:\project\work_workspace\spidhandle\src目录下生成文件
com_spidHandle_api_SpidHandle.h文件。
安装VC6.0开发工具。如果你是在windows下开发,那可以先生成DLL,这样你就可以在Windows下调试。其实JNI调用DLL和SO是一样的,只是运行的操作系统不一样而已。下面是如何用VC6.0创建一个DLL项目。
创建一个项目工程,名为spidhandle的工程,创建过程如下:
1、打开VC6.0->文件->新建
2、在弹出窗口中的工程选项卡中选择Win32 Dynamic-Link Library;工程名命名为spidhandle;点击确定。
3、在新的提示窗口中选择一个空白的DLL工程,点击完成。
4、在菜单的工具栏中选择选项,弹出选项窗口。切换到目录选项卡
5、在目录选项卡中新建目录,新建的目录为你JDK所在的目录下的include目录,如:
   D:\Program Files\Java\jdk1.6.0_16\include
  再新建一个目录,新建的目录为include文件夹下的win32目录,如
   D:\Program Files\Java\jdk1.6.0_16\include\win32
  此步主要是向工程引入jni所需要的头文件,如include中包含了jni.h,jni_md.h
6、将com_spidHandle_api_SpidHandle.h头文件拷贝到vc6.0工程spidHandle根目录下,将其添加到工程的Header Files,右键工程窗口中的Header Files,选择添加文件到目录下,选择工程路径下的com_spidHandle_api_SpidHandle.h文件。
7、在spidHandle工程根目录的文件夹中新建com_spidHandle_api_SpidHandle.h头文件对应的cpp文件,文件名称为com_spidHandle_api_SpidHandle.cpp,然后返回VC6.0操作界面,将其添加到工程的Source Files,右键工程窗口中的Source Files,选择添加文件到目录下,选择工程路径下的com_spidHandle_api_SpidHandle.cpp文件。
#include "com_spidHandle_api_SpidHandle.h"
#include <string.h>

#include "MD5.h"

const static char* version = "1201.01";

JNIEXPORT jstring JNICALL Java_com_spidHandle_api_SpidHandle_getSPID
 (JNIEnv *env , jobject obj, jstring path, jstring login_name, jstring password, jstring key)
{
	printf("-= com_spidHandle_api_SpidHandle Version  %s =- \n", version);
	char icpid[256];
	const char * md5="A6EIo8tuaKS";

	const char* login_user = env->GetStringUTFChars(login_name, false);
	const char* login_pwd = env->GetStringUTFChars(password, false);
	const char* md5_key = env->GetStringUTFChars(key, false);
	const char* path_str = env->GetStringUTFChars(path, false);
	
	memset(icpid, 0, 256);

	printf("login_user = %s\n", login_user);
	printf("path = %s\n", path_str);
	printf("login_pwd = %s\n", login_pwd);
	printf("md5_key = %s\n", md5_key);	

	// 不管播放哪个url 直接用这个加密  -_-|| 
	// pPath = "tmes_224";
	// 组建加密部分
	char *p=icpid;
	*p=strlen(login_user);
	p++;
	strcpy(p,login_user);
	p+=strlen(login_user);
	*p=strlen(path_str);
	p++;
	strcpy(p,path_str);
	p+=strlen(path_str);
	
	if(strlen(md5_key) > 1)
		md5 = md5_key;
	*p=strlen(md5);
	p++;
	strcpy(p,md5);
	p+=strlen(md5);

	MD5 m1;
	m1 << md5 << login_user << login_pwd;

	const char *pmd5 = m1.HexDigest();  // symbian专用
	char md5buf[256];
	memset(md5buf,0,256);
	memcpy( md5buf,pmd5,strlen(pmd5) ); // 结束symb