C#功能扩充: 让Java加入吧!

 

C#功能扩充: 让Java加入吧——C#启动JVM!

 

https://sourceforge.net/projects/jvcforcsharp/files/

这几天用Java写了许久的大作业。

一直纠结在Java的GUI程序设计上。

swing里的JList真变态,连Java核心那本书都把它放高级卷里。

起初写了点代码,界面太难看,实在受不了。

于是想起了微软。VS家族。

网上搜下"C++ jvm"能出来一堆啊,所以很欣喜地用++兄做着界面。

但是到了要显示文字的时候,它就麻烦了。

我还是喜欢使用+号连接字符串啊,厄,好吧,换C#。

再搜,没有代码了,怎么办?自己写吧。

 

我们知道C#可以运行非托管的代码,所以我们可以使用WindowsAPI

先用纯C++写了一遍不使用jni.h调用jvm的代码,这样到时候可以很轻松地转化为C#代码(不过不用jni.h,我们需要在C#里自己写个JavaENV和JavaVM的类):

 

 

 

 

下面让我简单介绍一下原理吧:

void* tmp是专门存临时指针数据的,因为VS动不动就提示不能转换,干脆设个临时值加(int)就强制转换了。

 

char optsstr[][100] = {"-Djava.compiler=NONE", "-Djava.class.path=.;testjvm.jar;", "-verbose:NONE"};

int optsptr[] = { 0,0,0 };

optsptr[i]=(int)((char*)(optsstr[i]));

上面这段就是optsptr各种存初始化参数的字符串指针。

 

int opts[] = {0,0,0,0,0,0};

这个opts有六个值因为在jni.h里JavaVMOption包含char*和int两项

这里有三个项,那就是6个值咯。

 

args.version=0x00010006;

args.nOptions=3;

tmp=opts;

args.options=(int)tmp;

args.ignoreUnrecognized=1;

这个是创建jvm需要的参数信息,没什么特别的。

 

HMODULE hdll=LoadLibrary(L"C://Program Files//Java//jre6//bin//client//jvm.dll");

_CreateJavaVM m_CreateJavaVM = (_CreateJavaVM)GetProcAddress(hdll, "JNI_CreateJavaVM");

用API动态价载DLL,一般人都会吧。

 

m_CreateJavaVM(&jvmp,&envp,&args);

这次调用有个特别的地方:

它的prototype是这样JNI_的CreateJavaVM(jvm**,env**,args*);

开始以为jvm**真的要int a;int* b=&a;int** c=&b;呢

而且更疯狂的是jni里的定义是jvm { functions* },就是jvm里有个函数表functions

jvm共有8个值,3个是reserved;env则有233个,4个是reserved。

于是先建了int flist[],再

int a=(convert to int)(flist);

int b=(convert to int)(&a);

int c=(convert to int)(&b);

结果第一次运行,然后读flist里什么都是0,没有变化!

连试了几次,最后还是扎到汇编里去了。

看了反汇编代码,跟进JNI_CreateJavaVM里面去,才知道这函数最后就只给jvm*和env*各一个值就出来了。

于是简单了,直接设两个int,然它们接指针数据吧。

 

int classname = 0;

char* classnameptr = "ljy/csharp/jvm/Hello";

classname=(int)classnameptr;

_FindClass m_FindClass=(_FindClass)(((int**)envp)[0][6]);

int _r = m_FindClass(envp,classname);

这个就是加载jar包里的类,其中要说的只有_FindClass m_FindClass=(_FindClass)(((int**)envp)[0][6]);

((int**)envp)[0][6]拆解开就是:

env* envp;

env { functions* }

functions { [0]reserved0 ... [6]FindClass ... }

所以envp[0]是得到functions的首地址,而envp[0][6]当然是得到第六个函数FindClass的地址咯

 

_DestroyJavaVM m_DestroyJavaVM = (_DestroyJavaVM)(((int**)jvmp)[0][3]);

m_DestroyJavaVM(jvmp);

用完了记得摧毁,这是好习惯…

 

现在原理清楚了,开始转成C#语言就好了。

先写NativeAPI,DllImport("Kernel32")去引入WindowsAPI吧。

再写NativeMemory,用Marshal各种直接操作内存…

最后JavaConnector,按刚写的C++代码重写成C#版就好了。

其中JavaConnector中还有JavaVM和JavaENV两个家伙。

JavaVM也就算了,JavaENV可是让人够受。

一方面JavaENV函数200多个啊,光写delegate就一堆了。

好在直接把jni.h里的东西拿出来,用VB写个小程序自动解析生成下代码,一切就顺利了。

 

我们用eclipse写个代码打成jar包吧:

 

 

 

到C#里试了一试,OK,搞定!

 
代码已经放到SourceForge上去了:
https://sourceforge.net/projects/jvcforcsharp/files/
不过目前的版本还会有错,好多函数参数是数组,必须先Marshal块空间再传,就暂时没改正了。
呵呵,最后:祝大家劳动节快乐!^_^
J.Y.Liu
2011.05.01

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值