`
7wolfs
  • 浏览: 183203 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Java 调用 C# DLL

    博客分类:
  • Java
阅读更多

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

 

package msg;

public class TestJNI {   
	   
	public native boolean MasSentMessage(String a, String b);   
	
    public native int add(int a, int b);   
    public native String submit(String a, String b);   
    public native boolean testBoolean(String a, String b);   
    static {   
        System.loadLibrary("CPP");   
    }   
    public static void main(String[] args) {   
        TestJNI t = new TestJNI();   
        
//        System.out.println(t.MasSentMessage("user", "pass"));  
//        System.out.println(t.add(2, 20));   
        System.err.println(t.submit("user", "pass"));
//        System.err.println(t.testBoolean("1", "pass"));
    }   
}

 

 

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

 
 

 

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

编辑C#文件如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OJMain
{
    public class OJEntrance
    {
        private int result;
        public int Result
        {
            get { return result + 10; }
            set { this.result = value; }
        }
        public string submit(string str1, string str2)
        {
           Console.WriteLine("成功调用了dll");
           return "CSharp:" + str1 + ":" + str2;
        }
        public bool testBoolean(string str1, string str2)
        {
            if (str1.Equals("true"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

 

 

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)。

// char* To jstring
jstring stringTojstring(JNIEnv* env, const char* pat)
{ 
	jclass strClass = env->FindClass("Ljava/lang/String;"); 
	jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); 
	jbyteArray bytes = env->NewByteArray(strlen(pat)); 
	env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); 
	jstring encoding = env->NewStringUTF("utf-8"); 
	return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); 
}
// jstring To char*
char* jstringTostring(JNIEnv* env, jstring jstr)
{
	char* rtn = NULL;
	jclass clsstring = env->FindClass("java/lang/String");
	jstring strencode = env->NewStringUTF("utf-8");
	jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
	jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
	jsize alen = env->GetArrayLength(barr);
	jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0)
	{
		rtn = (char*)malloc(alen + 1);
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0);
	return rtn;
}
// jstring To String
String^ jstringToStr(JNIEnv* env, jstring jstr)
{
	char* str = jstringTostring(env, jstr);
	String^ value = gcnew String(str);
	free(str);
	return value;
}

// String To jstring
jstring strTojstring(JNIEnv* env, String^ rtn)
{
	pin_ptr<const wchar_t> wch = PtrToStringChars(rtn);
	size_t convertedChars = 0;
	size_t sizeInBytes = ((rtn->Length + 1) * 2);
	char *ch = (char *)malloc(sizeInBytes);
	errno_t err = wcstombs_s(&convertedChars, 
		ch, sizeInBytes,
		wch, sizeInBytes);
	jstring js = stringTojstring(env, ch);
	free(ch);
	return js;
}

 

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

#include "jni.h"   
#include "jni_md.h"
#include "msg_TestJNI.h" 

//引入c#的库和命名空间
#using "CSharp.dll"
using namespace OJMain; 
……
…..
JNIEXPORT jint JNICALL Java_msg_TestJNI_add   
  (JNIEnv *env, jobject obj, jint a, jint b)   
{   
    //c#中的对象   
    OJEntrance ^o = gcnew OJEntrance();   
    o->Result = a + b;   
    return o->Result;   
}

JNIEXPORT jstring JNICALL Java_msg_TestJNI_submit
  (JNIEnv *env, jobject obj, jstring str1, jstring str2)  
{   
    //c#中的对象   
    OJEntrance ^o = gcnew OJEntrance();   
    return strTojstring(env, o->submit(jstringToStr(env,str1), jstringToStr(env,str2)));   
}

JNIEXPORT jboolean JNICALL Java_msg_TestJNI_testBoolean
  (JNIEnv *env, jobject obj, jstring str1, jstring str2)  
{   
    //c#中的对象   
    OJEntrance ^o = gcnew OJEntrance();   
    return o->testBoolean(jstringToStr(env,str1), jstringToStr(env,str2));  
}

 

5.5利用Visual Studio 2010生成CPP.dll

 

 

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

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

 

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

 

 

 

  • 大小: 29.5 KB
  • 大小: 15 KB
  • CPP.rar (9.3 MB)
  • 下载次数: 383
分享到:
评论
15 楼 yuekinger 2017-03-31  
若果 64bit 下正常 32位系统下不正常运行的 排除dll和java 版本后
还有 6楼的 在C++ 中初始化 C# 对象 OJEntrance ^o = gcnew OJEntrance();
出现 JVM 崩溃报错的
请把 生成的dll 文件复制到 java_home\bin 中 而不是 windows\system32 下面
这样就能解决了
路径问题!
14 楼 yuekinger 2017-03-31  
Win764 系统下成功! 实现 java 调用 c++ 链接调用c# dll
32位系统下不可以:
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xe0434352), pid=3224, tid=3084
#
# JRE version: 6.0_45-b06
# Java VM: Java HotSpot(TM) Client VM (20.45-b01 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [kernel32.dll+0x12aeb]
#
# An error report file with more information is saved as:
# C:\Developer\workspace\msg\hs_err_pid3224.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
13 楼 sdasds 2016-11-12  
sdasds 写道
pp1314 写道
x931100537 写道
Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.submit(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 的错误

怎么处理

解决了吗?我遇到一样错误,卡半天了。

同求,而且奇怪的是我一开始没遇到这个bug不知道改了哪里就遇到了,,,

尴尬,居然是因为我把函数名改错了个字母导致他没找到这个方法。。。。。
12 楼 sdasds 2016-11-12  
pp1314 写道
x931100537 写道
Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.submit(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 的错误

怎么处理

解决了吗?我遇到一样错误,卡半天了。

同求,而且奇怪的是我一开始没遇到这个bug不知道改了哪里就遇到了,,,
11 楼 pp1314 2016-09-02  
x931100537 写道
Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.submit(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 的错误

怎么处理

解决了吗?我遇到一样错误,卡半天了。
10 楼 pp1314 2016-09-02  
yaodingkun 写道
想请教下楼主,在64位win7下安装的eclipse和jdk是64位还是32位的?我按照楼主的方法尝试,最终抛出异常 Can't load IA 32-bit .dll on a AMD 64-bit platform 百度发现有人说无论时32位还是64位jdk下的jni_md.h 编译生成的dll都只适用于32位系统,我用的环境是win7x64,jdk x64,eclipse x64,那这样岂不是用jni做出的dll都不能在64位系统运行了?

这个你换一下32位jdk 就解决了
9 楼 pp1314 2016-09-02  
我想问问楼主调通了吗?我的一直报这个错Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.testBoolean(Ljava/lang/String;Ljava/lang/String;)Z
at msg.TestJNI.testBoolean(Native Method)
at msg.TestJNI.main(TestJNI.java:21)
8 楼 偶心壹旧 2016-07-23  
大神可以加下你的QQ吗?
7 楼 Alibert 2015-11-24  
楼主 是个好人
6 楼 x931100537 2015-09-08  
jni 里用这个,jvm 崩溃 
//c#中的对象    
    OJEntrance ^o = gcnew OJEntrance(); 
5 楼 x931100537 2015-09-07  
Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.submit(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 的错误

怎么处理
4 楼 yaodingkun 2015-07-15  
想请教下楼主,在64位win7下安装的eclipse和jdk是64位还是32位的?我按照楼主的方法尝试,最终抛出异常 Can't load IA 32-bit .dll on a AMD 64-bit platform 百度发现有人说无论时32位还是64位jdk下的jni_md.h 编译生成的dll都只适用于32位系统,我用的环境是win7x64,jdk x64,eclipse x64,那这样岂不是用jni做出的dll都不能在64位系统运行了?
3 楼 guohuaguang2008 2015-03-03  
非常棒
2 楼 a66756675 2015-02-27  
楼主 高深 但是我按照你说的做了 报Exception in thread "main" java.lang.UnsatisfiedLinkError: msg.TestJNI.submit(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 的错误,希望楼主帮我看看是哪出问题了 两个dll文件也已经放到jdk的bin目录下
1 楼 zzq2004 2014-04-12  
非常棒哦~~``

相关推荐

    java调用C#封装的dll方法

    ### Java调用C#封装的DLL方法 #### 第一种方法:Java利用JNA进行调用 **背景介绍:** 为了实现Java与C#之间的交互,一种常用的方式是通过调用C#封装的DLL文件来完成特定功能。这种方法涉及到.NET Framework与Java...

    Java调用C#DLL

    在IT行业中,跨语言通信是常见的需求,...总的来说,Java调用C# DLL涉及了跨平台通信、语言间互操作、库调用等多个复杂知识点。通过学习和实践,你可以掌握这些技术,增强你的编程能力,应对更多复杂系统的设计和开发。

    JAVA调用C#写的DLL例子

    JAVA 调用 C# 编写的 DLL 例子 在本篇文章中,我们将详细介绍如何使用 JAVA 调用 C# 编写的 DLL 文件。首先,我们需要了解什么是 DLL 文件,以及它在编程中的应用。 DLL 文件是一种动态链接库文件,它可以被多个...

    java调用C#封装的dll(jna,com)

    java调用C#封装的dll(jna,com)java调用C#封装的dll(jna,com)java调用C#封装的dll(jna,com)

    Java调用C# DLL的方法简介

    Java调用C# DLL的方法简介 在跨平台的软件开发中,有时我们需要在Java应用程序中调用由C#编写的动态链接库(DLL)。这通常涉及到两种主要的技术:JNI(Java Native Interface)和第三方工具。这篇知识文章将详细介绍...

    Java调用C# dll jacob包类资源.zip

    Java调用C# DLL是跨语言交互的一种常见需求,特别是在企业级应用开发中,可能会遇到已有的C#组件需要在Java环境中使用的场景。Jacob(Java COM Bridge)是一个开源项目,它提供了一个Java到COM(Component Object ...

    JAVA调用C#的DLL文件

    ### JAVA调用C# DLL文件的关键步骤和技术细节 #### 一、C#编写COM组件 在实际工作中,可能需要在不同编程语言之间进行交互。例如,一个基于Java的应用程序可能需要调用用C#编写的DLL文件来实现某些功能。这通常...

    JAVA通过JNI调用C#dll的整个项目工程

    Java通过JNI调用C# DLL是一个跨平台、跨语言的技术实践,主要应用于需要利用Java的稳定性和C#的高性能场景。JNI(Java Native Interface)是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。C# ...

    JavaInvokeCS-master_JAVA调用C#dll_fightsk4_C#_

    1. **C# DLL开发**:首先,在C#环境中创建一个动态链接库项目,编写需要暴露给Java调用的方法。C#提供了丰富的数据类型和API,可以创建复杂的功能模块。 2. **DLL导出**:在C#中,使用`[DllExport]`特性标记要导出...

    java调用c#样例

    标题"java调用c#样例"指的是使用Java语言通过Jacob库调用C#编写的动态链接库(DLL)。C# DLL通常包含.NET Framework中的方法和功能,而Java应用程序可以借助Jacob库来访问这些功能,从而实现跨语言的互操作性。 ...

    Java调用C#的DLL实现方案.rar

    以上是几种常见的Java调用C# DLL的实现方案,具体选择哪种方法取决于项目的具体需求,如性能、兼容性、复杂性和开发成本等因素。在实际应用中,可能需要综合考虑多种因素,选择最合适的方案。提供的"Java调用C#的DLL...

    JAVA调用C++/C#的DLL

    标题"JAVA调用C++/C#的DLL"涉及到的技术点主要集中在Java Native Interface(JNI)上,这是一种允许Java代码与其他编程语言(如C++或C#)进行交互的标准机制。下面我们将深入探讨这一主题。 首先,JNI是Java平台的...

    java调用C#封装的dll方法[归纳].pdf

    Java 调用 C# 封装的 DLL 方法概述 Java 调用 C# 封装的 DLL 方法是软件开发中的一种常见需求,本文将对这种方法进行归纳和总结。Java 调用 C# 封装的 DLL 方法有两种方式,一种是使用 JNA(Java Native Access)...

    Java通过JNI调用DLL动态库

    Java通过JNI调用DLL动态库,亲测试编写

    Java调用C#的DLL实现方案.docx

    这里提供了一种Java调用C#DLL的方法,主要涉及以下几个关键步骤: 1. **环境准备**: 首先,确保你拥有合适的开发环境。在这种情况下,使用的是Visual Studio 2019的社区版,它包含了.NET桌面开发、C++桌面开发...

    java调用c#写的dll

    本主题聚焦于如何使用Java调用由C#编写的DLL(动态链接库)文件。这种技术通常应用于系统集成、利用已有的C#组件或者服务,以及实现多语言环境下的协作开发。下面将详细阐述这个过程。 首先,C#编写的DLL是.NET框架...

    java使用jna调用c#中dll的方法详解

    C++项目配置为CLR(Common Language Runtime),可以引用并调用C#的方法,然后JNA可以进一步调用C++生成的.dll,从而实现了Java调用C#功能的需求。 在实际操作中,开发环境需包括Windows 10 x64操作系统、Visual ...

Global site tag (gtag.js) - Google Analytics