C#调用Java方法(详细实例)

简介: 原文:C#调用Java方法(详细实例)C#可以直接引用C++的DLL和转换JAVA写好的程序。最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方法转换成可以由C#直接调用的DLL C#调用c++ C#调用C++的例子网上很多,以一个C++的具体方法为例。
原文: C#调用Java方法(详细实例)

C#可以直接引用C++的DLL和转换JAVA写好的程序。最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方法转换成可以由C#直接调用的DLL

C#调用c++

C#调用C++的例子网上很多,以一个C++的具体方法为例。

C++代码

// 获取一帧图像数据
MVSMARTCAMCTRL_API int __stdcall MV_SC_GetOneFrame(IN void* handle, 
                                                  IN OUT unsigned char *pData , 
                                                  IN unsigned int nDataSize, 
                                                  IN OUT MV_SC_IMAGE_OUT_INFO* pstImageInfo);
// 结果数据缓存的上限
#define MV_SC_MAX_RESULT_SIZE       (1024*16)

// 输出帧的信息
typedef struct _MV_SC_IMAGE_OUT_INFO_
{
    unsigned short      nWidth;             // 图像宽
    unsigned short      nHeight;            // 图像高
    unsigned int        nFrameNum;          // 帧号
    unsigned int        nFrameLen;          // 当前帧数据大小
    unsigned int        nTimeStampHigh;     // 时间戳高32位
    unsigned int        nTimeStampLow;      // 时间戳低32位
    unsigned int        nResultType;           // 输出的消息类型
    // 根据消息类型对应不同的结构体
    unsigned char       chResult[MV_SC_MAX_RESULT_SIZE];
    unsigned int        nReserved[8];       // 保留
}MV_SC_IMAGE_OUT_INFO                                                  
                                                  

C#代码

    /// <summary>
    /// 获得相机所拍照片
    /// </summary>
    /// <param name="handle"></param>
    /// <returns></returns>
    [DllImport("MvSmartCamCtrl.dll")]
    public static extern int MV_SC_GetOneFrame(IntPtr handle, Byte[] pData, int nDataSize, out MV_SC_IMAGE_OUT_INFO pstDevInfo);
    
        // 输出帧的信息
    [StructLayout(LayoutKind.Sequential)]
    public struct MV_SC_IMAGE_OUT_INFO
    {
        public short nWidth;             // 图像宽
        public short nHeight;            // 图像高
        public int nFrameNum;          // 帧号
        public int nFrameLen;          // 当前帧数据大小
        public int nTimeStampHigh;     // 时间戳高32位
        public int nTimeStampLow;      // 时间戳低32位
        public int nResultType;           // 输出的消息类型
        // 根据消息类型对应不同的结构体
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024 * 16)]
        public MV_SC_RESULT_BCR chResult;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public int[] nReserved;
    }
 

这样我们把这个DLL放在程序根目录下,就能实现DLL方法的调用。

C#调用JAVA方法

IKVM.NET是一个针对Mono和微软.net框架的java实现,其设计目的是在.NET平台上运行java程序。它包含了以下的组件:用.NET实现的java虚拟机,java类库的.NET实现。
致力于在java和.NET之间交互的工具。

程序需求

我们有一个JAVA写好的Demo,传的参数是用Gzip进行压缩传到服务器的,代码如下:


package Demo;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import com.google.gson.Gson;

public class Demo
{

    public static String doPostClient(String json, String url)
    {
        HttpClient httpClient = new HttpClient();
        String rval = "";
        PostMethod postMethod = new PostMethod(url);
        try
        {
            Gson gson = new Gson();
            InputStream in = new ByteArrayInputStream(objectToByte(json));
            postMethod.setRequestBody(in);
            HttpClientParams params = new HttpClientParams();
            httpClient.setParams(params);
            httpClient.executeMethod(postMethod);
            byte[] b = postMethod.getResponseBody();
            String rtnData = (String) byteToObject(b);
            rval = gson.toJson(rtnData);
        } catch (Exception e)
        {
            rval="erro:"+e.getMessage();
        } finally
        {
            postMethod.releaseConnection();
        }
        return rval;
    }

    public static byte[] objectToByte(java.lang.Object obj)
    {
        byte[] bytes = null;
        ObjectOutputStream oo = null;
        try
        {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(out);
            gzip.write(obj.toString().getBytes("utf-8"));
            gzip.close();
            bytes = out.toByteArray();

        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            if (oo != null)
            {
                try
                {
                    oo.close();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return bytes;
    }

    private static java.lang.Object byteToObject(byte[] bytes)
    {
        String obj = "";
        ObjectInputStream oi = null;
        try
        {
            ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
            GZIPInputStream gzipi = new GZIPInputStream(bi);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipi, "UTF-8"));
            String line;
            while ((line = bufferedReader.readLine()) != null)
            {
                obj+=line;              
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            if (oi != null)
            {
                try
                {
                    oi.close();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return obj;
    }

}

这个代码我用C#改写了,用HttpWebRequest的方式传到服务器,服务器那边Gzip解压不了,查了原因是因为Java与C#的Byte类型值范围不同,我们有两种解决思路,一种是将这个JAVA做成webservice挂在服务器上,c#再去调用,第二种就是将这个方法编译成可由C#直接调用的DLL,由于这个方法功能比较单一,我们选取了后者。

环境配置

IKVM.NET 下载后解压得到BIN文件夹中的数据,用于JAR包转换和基础DLL。
IKVM.OpenJDK.ClassLibrary.dll用于C#程序接入。
下载地址:https://yunpan.cn/cBHTS5fXsIe9v 访问密码 0847。
将IKVM.NET的BIN文件夹的地址添加到环境变量。
计算机右键属性--高级系统设置--高级--环境变量--在系统变量中找到PATH--将BIN文件夹的地址添加进去,
在CMD中输入ikvmc 有帮助文档说明环境配置成功。
Bin文件夹下的IKVM.OpenJDK.Core.dll,IKVM.Runtime.dll,IKVM.Runtime.JNI.dll和IKVM.OpenJDK.ClassLibrary.dll为公共DLL,所有转换程序都需引用

转换步骤

1.确定引用关系:
该Demo的结构如下:
img_fe9ef7e4f13c1abf204f4d0fbdf328ba.png

Demo.jar 依赖于 commons-httpclient-3.1.jar 和 gson-2.4.jar
commons-httpclient-3.1.jar 依赖于 commons-logging-1.1.3.jar 和 commons-codec-1.6.jar

我们先将gson-2.4.jar,commons-logging-1.1.3.jar,commons-codec-1.6.jar 生成DLL,语法如下:

ikvmc JAR包物理路径。
win7系统默认生成在C:\Users\Administrator 这个文件夹下

commons-httpclient-3.1.dll 生成语法如下:

ikvmc commons-httpclient-3.1.jar -r:commons-logging-1.1.3.dll -r:commons-codec-1.6.dll

我们将Demo打包的名字为JavaApi.Demo 这样生成的 JavaApi.dll 生成语法如下:

ikvmc JavaApi.Demo.jar -r:commons-httpclient-3.1.dll -r:gson-2.4.dll

上面的文件都是相对应的物理路径,然后将所有生成的DLL添加到C#项目中引用,包括之前的公共DLL,引用到项目中所有引用的DLL如图:
img_893d991f76a021fb170b0744a50df89e.png

这样就可以直接在程序中使用这个java方法了
Demo.Demo.doPostClient(js, url);
第一个Demo java程序中的package名。
第二个Demo java程序中的class名。

目录
相关文章
|
1月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
1月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
74 9
|
29天前
|
安全 Java 开发者
Java中WAIT和NOTIFY方法必须在同步块中调用的原因
在Java多线程编程中,`wait()`和`notify()`方法是实现线程间协作的关键。这两个方法必须在同步块或同步方法中调用,这一要求背后有着深刻的原因。本文将深入探讨为什么`wait()`和`notify()`方法必须在同步块中调用,以及这一机制如何确保线程安全和避免死锁。
41 4
|
29天前
|
Java
深入探讨Java中的中断机制:INTERRUPTED和ISINTERRUPTED方法详解
在Java多线程编程中,中断机制是协调线程行为的重要手段。了解和正确使用中断机制对于编写高效、可靠的并发程序至关重要。本文将深入探讨Java中的`Thread.interrupted()`和`Thread.isInterrupted()`方法的区别及其应用场景。
30 4
|
27天前
|
Java 数据处理 数据安全/隐私保护
Java处理数据接口方法
Java处理数据接口方法
26 1
|
1月前
|
JSON 程序员 C#
使用 C# 比较两个对象是否相等的7个方法总结
比较对象是编程中的一项基本技能,在实际业务中经常碰到,比如在ERP系统中,企业的信息非常重要,每一次更新,都需要比较记录更新前后企业的信息,直接比较通常只能告诉我们它们是否指向同一个内存地址,那我们应该怎么办呢?分享 7 个方法给你!
|
1月前
|
C# UED SEO
C# 异步方法async / await任务超时处理
通过使用 `Task.WhenAny`和 `Task.Delay`方法,您可以在C#中有效地实现异步任务的超时处理机制。这种方法允许您在指定时间内等待任务完成,并在任务超时时采取适当的措施,如抛出异常或执行备用操作。希望本文提供的详细解释和代码示例能帮助您在实际项目中更好地处理异步任务超时问题,提升应用程序的可靠性和用户体验。
73 3
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
133 4
|
1月前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
213 2
|
1月前
|
Java Spring
JAVA获取重定向地址URL的两种方法
【10月更文挑战第17天】本文介绍了两种在Java中获取HTTP响应头中的Location字段的方法:一种是使用HttpURLConnection,另一种是使用Spring的RestTemplate。通过设置连接超时和禁用自动重定向,确保请求按预期执行。此外,还提供了一个自定义的`NoRedirectSimpleClientHttpRequestFactory`类,用于禁用RestTemplate的自动重定向功能。
101 0