Java调用 .NET dll

こ雲淡風輕ζ 提交于 2020-02-25 16:07:17

最近接了个蛋疼的活儿,用java调用c# 写的dll 模块,实现一个功能。研究了一下,找到JACOB和JNI4NET两个解决方法。虽然JNI4NET还可以实现 .NET 调用java,不过因为JACOB整个过程比较简单,而且JNI4NET已经很久不维护了,所以还是选择了JACOB。下面简单记录一下流程。

 

首先下载JACOB,可以在如下地址下载

https://sourceforge.net/projects/jacob-project/

下载后得到如下几个文件

因为我机器上用的64位java,所以后面的程序默认都是64位,不管是java还是c#。而且所有程序,包括VS的运行均通过管理员账户运行。

 

创建C# 类库工程,代码如下

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

namespace Jacob_NET
{
    public interface IClass1
    {
        string getStr(string str);
    }

    public class Class1 : IClass1
    {
        public string getStr(string str)
        {
            char[] tmp = str.ToCharArray();
            Array.Reverse(tmp);
            return new string(tmp);
        }
    }
}

之后将整个工程改为64位,先在解决方案中添加64位配置

 

然后在工程属性中将创建平台也改为64位

最后将程序设置为COM类型,并设置COM可见

至此c#的工作就完成了,编译生成即可得到dll

接下来要注册Jacob_NET.dll,可用管理员运行cmd并执行如下命令

C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe path\to\your\dll\Jacob_NET.dll

其中“path\to\your\dll”对应Jacob_NET.dll所在的路径。然后设置环境变量,把jacob-1.19-x64.dll所在的路径放在环境变量PATH中(也可以把jacob-1.19-x64.dll放在system32里)

 

最后新建java工程,我用的是eclipse,代码如下

package JacobTest;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class JacobTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        ActiveXComponent dotnetCom1 = null;
        try {
            dotnetCom1 = new ActiveXComponent("Jacob_NET.Class1");
            Variant var = Dispatch.call(dotnetCom1, "getStr","abc123");
            String str = var.toString(); //返回值
            System.out.println(str);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if(dotnetCom1 != null) {
            dotnetCom1.safeRelease();
            }
        }
	}

}

然后引入jacob.jar

 

最后编译运行java工程即可得到结果。

 

整个工程文件(包括jacob包)可在如下地址下载

https://download.csdn.net/download/u014559935/12103757

 

值得注意的是,如果java调用的.NET dll中包含wpf控件,可能需要STA线程模型,则以上简单的调用方法会失败,需要将代码改为如下形式

package JacobTest;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchProxy;
import com.jacob.com.STA;
import com.jacob.com.Variant;

public class JacobTest extends STA {
    public static ActiveXComponent sC;
    public static Dispatch sControl = null;
    public static DispatchProxy sCon = null;

    public boolean OnInit()
    {
        try {
            System.out.println("OnInit");
            System.out.println(Thread.currentThread());

            sC = new ActiveXComponent("Jacob_NET.Class2");
            sControl = (Dispatch)sC.getObject();
            sCon = new DispatchProxy(sControl);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public void OnQuit()
    {
        System.out.println("OnQuit");
    }

    public static void main(String[] args) throws Exception {
        try {
            ComThread.InitSTA();
            JacobTest obj = new JacobTest();
            Thread.sleep(1000);   // 给线程初始化时间

            Dispatch sc = sCon.toDispatch();
            Variant var1 = Dispatch.call(sc, "ShowResult", "Hello, world");

            obj.quit();
            System.out.println("called quit");
        } catch (ComException ex) {
            ex.printStackTrace();
        } finally {
            ComThread.Release();
        }
    }
}

以上代码调用的C# dll中,包含一个ShowResult方法,在该方法中,创建了一个WPF窗口,并将参数显示在该窗口中。因为比较简单,此处略去这部分代码。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!