[置顶] java中使用C++指针实现java调用C#

运行结果图:

[置顶] 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 <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");			
	}
}


如需转载,请注明出处.
[email protected]

你可能感兴趣的:([置顶] java中使用C++指针实现java调用C#)