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

C#能够直接引用C++的DLL和转换JAVA写好的程序。最近因为工做缘由接触这方面比较多,根据实际需求,咱们经过一个具体例子把一个JAVA方法转换成能够由C#直接调用的DLLjava

C#调用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方法的调用。web

C#调用JAVA方法

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

程序需求

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

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,因为这个方法功能比较单一,咱们选取了后者。c#

环境配置

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的结构以下:
服务器

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如图:

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

相关文章
相关标签/搜索