java中使用C++指针实现java调用C#

来源:互联网 发布:淘宝怎么下载到桌面 编辑:程序博客网 时间:2024/06/15 09:46

运行结果图:


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 __cplusplusextern "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

原创粉丝点击