運(yùn)行結(jié)果圖:
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);}
頭文件產(chǎn)生命令行:javah jxdo.iclr.Access得到如下頭文件:/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* 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
CPP對于頭文件的實(shí)現(xiàn):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;}
其它省去,可以按這個(gè)方式繼續(xù)實(shí)現(xiàn)頭文件中的代碼……
代碼說明:void* umgdClr存放了一個(gè)指針
Java_jxdo_iclr_Access_nGetType 返回一個(gè)拖管代碼Type類型的指針,返回給JAVA端,便于創(chuàng)建拖管對象。
Java_jxdo_iclr_Access_nCreateInstance__I中的iTypePtr參數(shù)就是上面返回的指針。
都說JAVA中沒有指針,其實(shí)這個(gè)int值,就是一個(gè)指針值。
CPP中使用混編,可以得到拖管對象指針:{ int iPtr = GCHandle::ToIntPtr(GCHandle::Alloc(obj))。ToInt32();return iPtr;} iPtr就是對象指針,可以直接設(shè)置給jint,返回到JAVA代碼中。
從JAVA中將指針值重新傳到CPP中的處理,需要恢復(fù)出這個(gè)指針Object^ ikvmClrBridge::getObject(int iPtr)
{ GCHandle gch = GCHandle::FromIntPtr(IntPtr(iPtr));return gch.Target;}
CPP的拖管代碼(ikvmClrBridge類的頭文件):ref class ikvmClrBridge { private:Assembly^ asmLoad;Dictionary^ 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類的頭文件具體實(shí)現(xiàn)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);}
其它省去,可以按這個(gè)方式繼續(xù)實(shí)現(xiàn)拖管頭文件中的代碼……
讀者可以擴(kuò)充,實(shí)現(xiàn)參數(shù)的傳入,方法的返回值,屬性等代碼的調(diào)用。
測試的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端調(diào)用代碼: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");}