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

目录
相关文章
|
13天前
|
Java 数据处理 数据安全/隐私保护
Java处理数据接口方法
Java处理数据接口方法
20 1
|
26天前
|
JSON 程序员 C#
使用 C# 比较两个对象是否相等的7个方法总结
比较对象是编程中的一项基本技能,在实际业务中经常碰到,比如在ERP系统中,企业的信息非常重要,每一次更新,都需要比较记录更新前后企业的信息,直接比较通常只能告诉我们它们是否指向同一个内存地址,那我们应该怎么办呢?分享 7 个方法给你!
|
29天前
|
C# UED SEO
C# 异步方法async / await任务超时处理
通过使用 `Task.WhenAny`和 `Task.Delay`方法,您可以在C#中有效地实现异步任务的超时处理机制。这种方法允许您在指定时间内等待任务完成,并在任务超时时采取适当的措施,如抛出异常或执行备用操作。希望本文提供的详细解释和代码示例能帮助您在实际项目中更好地处理异步任务超时问题,提升应用程序的可靠性和用户体验。
51 3
|
2月前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
50 17
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
87 4
|
1月前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
103 2
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
23 3
|
2月前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
20 2
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
22 1