您的位置:首页 > 编程语言 > C语言/C++

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

2011-10-27 07:05 981 查看
运行结果图:



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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: