运行结果图:

  

java中使用C++指针实现java调用C#_第1张图片

  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  /* 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对于头文件的实现: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 ^ 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");}