语言混编之c调用java

经过验证可以实现,先将实现代码贴出,以备以后使用。

本文默认你的java开发环境已经安装成功,并且对于java语言和c++语言有过了解。

编写测试用类:Demo.java

代码如下:

public class Demo
{
 public static int COUNT = 8;
 
 private String msg;
 private int[] counts;
 
 public Demo ()
 {
  this ("default constructor");
 }

 public Demo (String msg)
 {
  this.msg = msg;
  this.counts = null;
 }

 public String getMessage ()
 {
  return msg;
 }
 
 public static String getHelloWorld ()
 {
  return "hello world!";
 }
 public String append (String str, int i)
 {
  return str + i;
 }
 public int[] getCounts ()
 {
  return counts;
 }

 public void setCounts (int[] counts)
 {
  this.counts = counts;
 }

 public void throwExcp () throws IllegalAccessException
 {
  throw new IllegalAccessException ("exception occurs");
 }
}

由于在java中能够使用函数重载,所以在c语言中调用java是需要确定究竟是调用的是那个函数。在jdk中提供了javap程序。

Javap将一个类和它的方法的一些转储信息输出到标准输出。该工具不把代码反编译为java源代码,但是它会把字节代码反汇编成为由Java虚拟机规范定义的字节代码指令。其用法如下:

-l     输出本地变量表

-public    输出公用类名和方法名

-protected   输出类的受保护方法

-private   输出类的似有方法

-verbose  输出类的栈的信息和本地方法的个数

回到原来主题:

javap -s -p Demo

无法上传图片^_^想象一下吧。在输出中找到如下的语句:

public java.lang.String append(java.lang.String, int);
  Signature: (Ljava/lang/String;I)Ljava/lang/String;

在vs2008中新建一个工程(win32 console application),配置工程属性:将jdk中include目录下的头文件加入到工程中,并将该文夹下的win32子目录下的header file同样加入到工程中。

新建main.cpp

代码如下:

#include <Windows.h>
#include "jni.h"
#include <string>
#include <iostream>

using namespace std;

jstring NewJString (JNIEnv* env, LPCTSTR str);
string  JStringToCString (JNIEnv *env, jstring str);

int main ()
{
 typedef jint (WINAPI* PFunCreateJavaVM) (JavaVM**, void**, void*);

 int res;
 JavaVMInitArgs vm_args;
 JavaVMOption options[3];
 JavaVM* jvm;
 JNIEnv* env;
 
 options[0].optionString = options[0].optionString = "-Djava.compiler=NONE";
 //classpath should be set to find the .class file in the following
 //here we put the class file in the directory c:\ Demo.class
 options[1].optionString = "-Djava.class.path=.;C:\\";
 options[2].optionString = "-verbose:NONE";

 vm_args.version = JNI_VERSION_1_4;  
 vm_args.nOptions = 3;  
 vm_args.options = options;

 vm_args.ignoreUnrecognized = JNI_TRUE;
 
 //load the dll
 HINSTANCE hInstance = ::LoadLibrary("C:\\Program Files\\Java\\jdk1.6.0_10\\jre\\bin\\client\\jvm.dll");
 if (hInstance == NULL)
  return 1;

 PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");

 res = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);  
 if (res < 0)  
 {  
  return -1;  
 }  

 jclass cls = env->FindClass("Demo");

 jobject obj = env->AllocObject(cls);

 jmethodID mid = env->GetMethodID(cls, "append","(Ljava/lang/String;I)Ljava/lang/String;");  

 const char szTest[] = "HELLO WORLD";  
 jstring arg = NewJString(env, szTest);  
 jstring msg = (jstring) env->CallObjectMethod(obj, mid, arg, 12);  
 cout << JStringToCString(env, msg);

 jvm->DestroyJavaVM();  
 ::FreeLibrary(hInstance);  
 return 0;  
}

string  JStringToCString (JNIEnv *env, jstring str)// (jstring str, LPTSTR desc, int desc_len)  
{  
 if(str==NULL)  
 {  
  return "";  
 }

 int len = env->GetStringLength(str);  
 wchar_t *w_buffer = new wchar_t[len+1];  
 //char* w_buffer = new char [len + 1];
 char *c_buffer = new char[2*len+1];  
 ZeroMemory(w_buffer,(len+1)*sizeof(wchar_t));  
 
 const jchar * jcharString = env->GetStringChars(str, 0);
 wcscpy(w_buffer,(wchar_t*)jcharString);     
 
 env->ReleaseStringChars(str,jcharString);  
 ZeroMemory(c_buffer,(2*len+1)*sizeof(char));  
 len = WideCharToMultiByte(CP_ACP, 0, w_buffer, len, c_buffer, 2 * len, NULL, NULL);  
 string cstr = c_buffer;  
 delete[] w_buffer;  
 delete[] c_buffer;  

 return cstr;  
}  

jstring NewJString(JNIEnv *env, LPCTSTR str)  
{  
 if(!env || !str)  
 {  
  return 0;  
 }  
 int slen = strlen(str);  
 jchar* buffer = new jchar[slen];  
 int len = MultiByteToWideChar(CP_ACP,0,str,strlen(str), (LPWSTR)buffer,slen);  
 if(len>0 && len < slen)  
 {  
  buffer[len]=0;  
 }  
 jstring js = env->NewString(buffer,len);  
 delete [] buffer;  
 return js; 

注意上面的路径的使用需要根据本地的文件路径来设置。编译运行即可。

转载于http://public0821.javaeye.com/blog/423941

posted @ 2010-01-12 11:32  qiang.xu  阅读(7206)  评论(0编辑  收藏  举报