Java 调用 C# DLL

Java无法直接调用C# dll,需要通过经过桥接的方式,进行中继转发一下请求。查阅大量资料,做了大量实验,不停的调试、排错之后,期间试过jni4net,不过这个插件需要修改原有的C# DLL内容,还会生成一些额外的Java代码,jni4net侵入性太多,将它排除。最后通过管理性的C++桥接方式,成功完成了Java调用C# DLL。

国内很多文章都是只有文章,没有在文中附上完整的代码工程,导致读者做实验时非常麻烦。而老外经常会带上完整的代码工程,这让读者做实验时参考起来非常方便。本文附上完整的Java、C++、CSharp代码工程,供大家参考。

 

实验环境:

64位 Win 7

jdk1.7.0_51

Eclipse 4.3.1

Visual Studio 2010

 

 

具体的实现步骤如下:

1,新建一个Java项目TestJNI,定义一个Java客户端类 TestJNI.java

 

Java代码   收藏代码
  1. package msg;  
  2.   
  3. public class TestJNI {     
  4.          
  5.     public native boolean MasSentMessage(String a, String b);     
  6.       
  7.     public native int add(int a, int b);     
  8.     public native String submit(String a, String b);     
  9.     public native boolean testBoolean(String a, String b);     
  10.     static {     
  11.         System.loadLibrary("CPP");     
  12.     }     
  13.     public static void main(String[] args) {     
  14.         TestJNI t = new TestJNI();     
  15.           
  16. //        System.out.println(t.MasSentMessage("user", "pass"));    
  17. //        System.out.println(t.add(2, 20));     
  18.         System.err.println(t.submit("user""pass"));  
  19. //        System.err.println(t.testBoolean("1", "pass"));  
  20.     }     
  21. }  

 

 

2,调用JDK里的javah命令通过TestJNI.java类生成msg_TestJNI.h文件,javah设置如下, 

 
 

 

3,在Visual Studio 2010新建一个C#项目CSharp(项目类型为Visual C# -->Windows?类库)

编辑C#文件如下:

C#代码   收藏代码
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace OJMain  
  7. {  
  8.     public class OJEntrance  
  9.     {  
  10.         private int result;  
  11.         public int Result  
  12.         {  
  13.             get { return result + 10; }  
  14.             set { this.result = value; }  
  15.         }  
  16.         public string submit(string str1, string str2)  
  17.         {  
  18.            Console.WriteLine("成功调用了dll");  
  19.            return "CSharp:" + str1 + ":" + str2;  
  20.         }  
  21.         public bool testBoolean(string str1, string str2)  
  22.         {  
  23.             if (str1.Equals("true"))  
  24.             {  
  25.                 return true;  
  26.             }  
  27.             else  
  28.             {  
  29.                 return false;  
  30.             }  
  31.         }  
  32.     }  
  33. }  

 

 

4,利用Visual Studio 2010 生成dll。

如果调用C#项目的Java客户端在64位的机器上,需要重新生成dll,在Visual Studio 2010的生成参数设置如下,将目标平台设为“Any CPU”



 

 

5,在Visual Studio 2010中新建一个win32 dll模式的C++项目CPP,为了在Java和C#之间的调用建立通道并进行转接。

 

5.1设置两个项目属性

一,项目属性-->配置属性--> 常规:“公共语言运行时支持”设为“公共语言运行时支持(/clr)”

二,项目属性-->配置属性-->C/C++-->代码生成:“运行库”设为“多线程DLL(/MD)”

 

5.2  C++源文件的目录里放置如下内容:

  • JDK目录里的两个h文件(jni.h,jni_md.h);
  • Java项目中生成的msg_TestJNI.h;
  • C#项目CSharp中生成的CSharp.dll ;

5.3编写jstring 和 string的相互转换功能,完整代码参见附件 CPP.rar(CPP.cpp)。

Cpp代码   收藏代码
  1. // char* To jstring  
  2. jstring stringTojstring(JNIEnv* env, const char* pat)  
  3. {   
  4.     jclass strClass = env->FindClass("Ljava/lang/String;");   
  5.     jmethodID ctorID = env->GetMethodID(strClass, "<init>""([BLjava/lang/String;)V");   
  6.     jbyteArray bytes = env->NewByteArray(strlen(pat));   
  7.     env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);   
  8.     jstring encoding = env->NewStringUTF("utf-8");   
  9.     return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);   
  10. }  
  11. // jstring To char*  
  12. char* jstringTostring(JNIEnv* env, jstring jstr)  
  13. {  
  14.     char* rtn = NULL;  
  15.     jclass clsstring = env->FindClass("java/lang/String");  
  16.     jstring strencode = env->NewStringUTF("utf-8");  
  17.     jmethodID mid = env->GetMethodID(clsstring, "getBytes""(Ljava/lang/String;)[B");  
  18.     jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);  
  19.     jsize alen = env->GetArrayLength(barr);  
  20.     jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);  
  21.     if (alen > 0)  
  22.     {  
  23.         rtn = (char*)malloc(alen + 1);  
  24.         memcpy(rtn, ba, alen);  
  25.         rtn[alen] = 0;  
  26.     }  
  27.     env->ReleaseByteArrayElements(barr, ba, 0);  
  28.     return rtn;  
  29. }  
  30. // jstring To String  
  31. String^ jstringToStr(JNIEnv* env, jstring jstr)  
  32. {  
  33.     char* str = jstringTostring(env, jstr);  
  34.     String^ value = gcnew String(str);  
  35.     free(str);  
  36.     return value;  
  37. }  
  38.   
  39. // String To jstring  
  40. jstring strTojstring(JNIEnv* env, String^ rtn)  
  41. {  
  42.     pin_ptr<const wchar_t> wch = PtrToStringChars(rtn);  
  43.     size_t convertedChars = 0;  
  44.     size_t sizeInBytes = ((rtn->Length + 1) * 2);  
  45.     char *ch = (char *)malloc(sizeInBytes);  
  46.     errno_t err = wcstombs_s(&convertedChars,   
  47.         ch, sizeInBytes,  
  48.         wch, sizeInBytes);  
  49.     jstring js = stringTojstring(env, ch);  
  50.     free(ch);  
  51.     return js;  
  52. }  

 

5.4  编写C++的管理类, 完整代码参见附件 CPP.rar(CPP.cpp)

Cpp代码   收藏代码
  1. #include "jni.h"     
  2. #include "jni_md.h"  
  3. #include "msg_TestJNI.h"   
  4.   
  5. //引入c#的库和命名空间  
  6. #using "CSharp.dll"  
  7. using namespace OJMain;   
  8. ……  
  9. …..  
  10. JNIEXPORT jint JNICALL Java_msg_TestJNI_add     
  11.   (JNIEnv *env, jobject obj, jint a, jint b)     
  12. {     
  13.     //c#中的对象     
  14.     OJEntrance ^o = gcnew OJEntrance();     
  15.     o->Result = a + b;     
  16.     return o->Result;     
  17. }  
  18.   
  19. JNIEXPORT jstring JNICALL Java_msg_TestJNI_submit  
  20.   (JNIEnv *env, jobject obj, jstring str1, jstring str2)    
  21. {     
  22.     //c#中的对象     
  23.     OJEntrance ^o = gcnew OJEntrance();     
  24.     return strTojstring(env, o->submit(jstringToStr(env,str1), jstringToStr(env,str2)));     
  25. }  
  26.   
  27. JNIEXPORT jboolean JNICALL Java_msg_TestJNI_testBoolean  
  28.   (JNIEnv *env, jobject obj, jstring str1, jstring str2)    
  29. {     
  30.     //c#中的对象     
  31.     OJEntrance ^o = gcnew OJEntrance();     
  32.     return o->testBoolean(jstringToStr(env,str1), jstringToStr(env,str2));    
  33. }  

 

5.5利用Visual Studio 2010生成CPP.dll

 

 

6,JDK的bin目录里放置如下内容

  • C# 项目CSharp中生成的CSharp.dll ;
  • C++项目CPP中生成的CPP.dll;

 

7,在Java项目TestJNI中 运行TestJNI,调用C# dll。


http://dl2.iteye.com/upload/attachment/0096/0022/10054a95-4699-3fec-b917-af138ab881f7.zip

http://dl2.iteye.com/upload/attachment/0096/0023/c84700d7-2a42-39c7-af4c-0cee599bb1cb.rar

http://dl2.iteye.com/upload/attachment/0096/0025/4544d588-7d4c-3593-b72f-948f53483a18.rar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值