最近接了个蛋疼的活儿,用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窗口,并将参数显示在该窗口中。因为比较简单,此处略去这部分代码。
来源:oschina
链接:https://my.oschina.net/propagator/blog/3158548