运行结果图:
Access.java代码:
package jxdo.iclr;
public class Access {
private native void nLoad(String asmFileName);
private native int nGetType(String typeName);
private native int nCreateInstance(int iTypePointer);
private native int nCreateInstance(String typeName);
private native void nInvokeStatic(int iTypePointer, String methodName);
private native void nInvoke(int iObjectPointer, String methodName);
static
{
System.loadLibrary("NXDO.IKMX");
}
public static Access load(String asmFileName)
{
Access ace = new Access();
ace.nLoad(asmFileName);
return ace;
}
public int getType(String typeName)
{
return this.nGetType(typeName);
}
public int createInstance(int iTypePointer)
{
return this.nCreateInstance(iTypePointer);
}
public int createInstance(String typeName)
{
return this.nCreateInstance(typeName);
}
public void invokeStatic(int iTypePointer, String methodName)
{
this.nInvokeStatic(iTypePointer,methodName);
}
public void invoke(int iObjectPointer, String methodName)
{
this.nInvoke(iObjectPointer,methodName);
}
}
头文件产生命令行:
javah jxdo.iclr.Access
得到如下头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jxdo_iclr_Access */
#ifndef _Included_jxdo_iclr_Access
#define _Included_jxdo_iclr_Access
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jxdo_iclr_Access
* Method: nLoad
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_jxdo_iclr_Access_nLoad
(JNIEnv *, jobject, jstring);
/*
* Class: jxdo_iclr_Access
* Method: nGetType
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_jxdo_iclr_Access_nGetType
(JNIEnv *, jobject, jstring);
/*
* Class: jxdo_iclr_Access
* Method: nCreateInstance
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_jxdo_iclr_Access_nCreateInstance__I
(JNIEnv *, jobject, jint);
/*
* Class: jxdo_iclr_Access
* Method: nCreateInstance
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_jxdo_iclr_Access_nCreateInstance__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: jxdo_iclr_Access
* Method: nInvokeStatic
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_jxdo_iclr_Access_nInvokeStatic
(JNIEnv *, jobject, jint, jstring);
/*
* Class: jxdo_iclr_Access
* Method: nInvoke
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_jxdo_iclr_Access_nInvoke
(JNIEnv *, jobject, jint, jstring);
#ifdef __cplusplus
}
#endif
#endif
CPP对于头文件的实现:
void* umgdClr;
JNIEXPORT void JNICALL Java_jxdo_iclr_Access_nLoad(JNIEnv* env, jobject obj, jstring asmFileName)
{
String^ dllName = ikvmClrBridge::ToClrString(env,asmFileName);
ikvmClrBridge^ mgd = gcnew ikvmClrBridge();
try
{
mgd->Load(dllName);
}
catch (Exception^ ex)
{
const char* exStr = ikvmClrBridge::ToCppChar(ex->Message);
jclass errclass = env->FindClass("java/lang/Exception");
env->ThrowNew(errclass, exStr);//向java中抛出异常
ikvmClrBridge::FreeCppString(exStr);
return;
}
umgdClr = ikvmClrBridge::getPtrVoid(mgd);
}
JNIEXPORT jint JNICALL Java_jxdo_iclr_Access_nGetType(JNIEnv* env, jobject obj, jstring clrTypeName)
{
ikvmClrBridge^ mgd = (ikvmClrBridge^)(ikvmClrBridge::getObject(umgdClr));
String^ typeName = ikvmClrBridge::ToClrString(env,clrTypeName);
Type^ type = nullptr;
try
{
type = mgd->GetType(typeName);
}
catch (Exception^ ex)
{
const char* exStr = ikvmClrBridge::ToCppChar(ex->Message);
jclass errclass = env->FindClass("java/lang/Exception");
env->ThrowNew(errclass, exStr);
ikvmClrBridge::FreeCppString(exStr);
return 0;
}
return ikvmClrBridge::getPtrInt(type);
}
JNIEXPORT jint JNICALL Java_jxdo_iclr_Access_nCreateInstance__I(JNIEnv* env, jobject obj, jint iTypePtr)
{
ikvmClrBridge^ mgd = (ikvmClrBridge^)(ikvmClrBridge::getObject(umgdClr));
int clrTypePtr = iTypePtr;
Object^ clrObj = nullptr;
try
{
clrObj = mgd->CreateInstance((Type^)(ikvmClrBridge::getObject(clrTypePtr)));
}
catch (Exception^ ex)
{
const char* exStr = ikvmClrBridge::ToCppChar(ex->Message);
jclass errclass = env->FindClass("java/lang/Exception");
env->ThrowNew(errclass, exStr);
ikvmClrBridge::FreeCppString(exStr);
return 0;
}
int iObjPtr = GCHandle::ToIntPtr(GCHandle::Alloc(clrObj)).ToInt32();
return iObjPtr;
}
其它省去,可以按这个方式继续实现头文件中的代码...
代码说明:
void* umgdClr存放了一个指针
Java_jxdo_iclr_Access_nGetType 返回一个拖管代码Type类型的指针,返回给JAVA端,便于创建拖管对象.
Java_jxdo_iclr_Access_nCreateInstance__I中的iTypePtr参数就是上面返回的指针.
都说JAVA中没有指针,其实这个int值,就是一个指针值.
CPP中使用混编,可以得到拖管对象指针:
{
int iPtr = GCHandle::ToIntPtr(GCHandle::Alloc(obj)).ToInt32();
return iPtr;
}
iPtr就是对象指针,可以直接设置给jint,返回到JAVA代码中.
从JAVA中将指针值重新传到CPP中的处理,需要恢复出这个指针
Object^ ikvmClrBridge::getObject(int iPtr)
{
GCHandle gch = GCHandle::FromIntPtr(IntPtr(iPtr));
return gch.Target;
}
CPP的拖管代码(ikvmClrBridge类的头文件):
ref class ikvmClrBridge
{
private:
Assembly^ asmLoad;
Dictionary<String^, Type^>^ dicTypes;
MethodInfo^ GetMethod(Type^ type,String^ methodName);
internal:
static int getPtrInt(Object^ obj);
static void* getPtrVoid(Object^ obj);
static Object^ getObject(int iPtr);
static Object^ getObject(void* voidPtr);
static String^ ToClrString(JNIEnv* env, jstring jstr);
static const char* ToCppChar(String^ str);
static void FreeCppString(const char* str);
public:
ikvmClrBridge(void);
void Load(String^ dllName);
Type^ GetType(String^ typeName);
Object^ CreateInstance(Type^ type);
Object^ CreateInstance(String^ typeName);
void Invoke(Object^ obj, String^ methodName);
void Invoke(Type^ type,String^ methodName);
};
拖管代码ikvmClrBridge类的头文件具体实现
void ikvmClrBridge::Load(String^ dllName)
{
String^ asmDllName = dllName;
if (!File::Exists(asmDllName))
{
String^ path = AppDomain::CurrentDomain->BaseDirectory;
asmDllName = Path::Combine(path, asmDllName);
}
if (!File::Exists(asmDllName))
throw gcnew FileNotFoundException("clr not found file:" + dllName);
this->asmLoad = Assembly::LoadFile(asmDllName);
}
Type^ ikvmClrBridge::GetType(String^ typeName)
{
bool b = this->dicTypes->ContainsKey(typeName);
if (b) return this->dicTypes[typeName];
Type^ type = this->asmLoad->GetType(typeName);
if (type == nullptr)
throw gcnew TargetException("clr not found type:"+typeName);
this->dicTypes->Add(typeName, type);
return type;
}
Object^ ikvmClrBridge::CreateInstance(Type^ type)
{
return Activator::CreateInstance(type);
}
其它省去,可以按这个方式继续实现拖管头文件中的代码...
读者可以扩充,实现参数的传入,方法的返回值,属性等代码的调用.
测试的C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassLibrary1
{
public class Class1
{
public void Who()
{
Console.WriteLine("i'm C# Class1!");
}
public static void WhoStatic()
{
Console.WriteLine("i'm C#,static!");
}
}
public class Class2
{
public void Who()
{
Console.WriteLine("i'm C# Class2!");
}
}
}
JAVA端调用代码:
package jxdo.iclr;
public class test {
public static void main(String[] args) {
Access ace = Access.load("d:\\ClassLibrary1.dll");
int iType = ace.getType("ClassLibrary1.Class1");
ace.invokeStatic(iType, "WhoStatic");
int iObj = ace.createInstance(iType);
ace.invoke(iObj, "Who");
int iObj2 = ace.createInstance("ClassLibrary1.Class2");
ace.invoke(iObj2, "Who");
}
}
如需转载,请注明出处.
javasuki@hotmail.com