论坛首页 Java企业应用论坛

java 如何调用com组件接口方法。

浏览 14470 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-09-10  

大家都知道com组件的接口方法是基于windows下开发的。要在java里调的话。就要用到JNI技术。JNI是Java Native Interface的缩写,JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。尤其是c++或是c写的com组件接口。

JNI(Java Native Interface)的书写步骤 一般分为以下:

1、      编写带有native声明的方法的java类
2、    使用javac命令编译所编写的java类
3、    使用javah ?jni java类名生成扩展名为h的头文件
4、    使用C/C++实现本地方法
5、    将C/C++编写的文件生成动态连接库

写个例子来说明,最常用的还是hello  world 的例子吧。

class HelloWorld {
public native void displayHelloWorld();

static {
System.loadLibrary("hello");
}

public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}

注意:LoadLibrary中的DLL文件名称可以随便定.只要做好的动态链接库改名成这个字符串就可以了

如果你想将一个方法声明为本地方法的话,必须将方法声明为native方法,并且不能实现。 做好该步准备以后,用javac TestNative.java生成.class.检验语法.  语法检查通过以后,用javah HelloWorld 生成.h的C头文件. 然后打开VC++6.0,新建->; 工程 ->; win32 Dynamic-Link Library .在向导中选择空工程. 把刚才javah生成的那个头文件加入工程 .然后 文件->;新建->;textFile 自己做一个.c文件.实现自己的native函数.例子如下:

1 #include
2 #include "HelloWorld.h"
3 #include

4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}

备注:
其中的HelloWorld.h通常在 jdk\include\ 可以先拷贝到VC安装目录下的include目录下。一劳永逸,以后可以方便使用JNI技术,全编译一下工程,如果没有出错,则此时生成动态链接库成成功。把动态链接库拷贝到HelloWorld .java所在的目录上. 
 运行java HelloWorld 看结果吧.

 

在实际应用中比较麻烦是数据类型的转换。因为要解决java和C++数据类型互通的问题。比如java里的string 如何映射为c++里相应的字符。还希望大家一起讨论。


 

 

   发表时间:2007-09-11  
听说过javacom
0 请登录后投票
   发表时间:2007-09-13  
如果要用java调com,不要用jni,因为jni搞不定com的事件通知

选择一:商业用途建议用J-Integra for COM。
优点:稳定,使用简单
缺点:只有商业版,收费的,贵死。
取巧的办法:weblogic中带了这套工具,听说weblogic很多盗版的....

例如以一个com中有add(int,int)的方法,并有一个事件通知。样例代码如下:
public class ConnectPointComTest {
    static {
        System.setProperty("JINTEGRA_NATIVE_MODE", "");
        System.setProperty("JINTEGRA_COINIT_VALUE", "2");
    }

    public void run() {
        try {
            _IDispConnectEventsAdapter evt=new _IDispConnectEventsAdapter();
            final DispConnect dcon = new DispConnect();
            dcon.add_IDispConnectEventsListener(evt);
            dcon.add(14, 5);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

dispConn开头的类用J-Integra for COM提供的工具生成的。
使用起来就象使用普通的java类一样的简单。

选择二: JACOB - Java COM Bridge
优点:开源,免费的,效果高
缺点:超过10个并发就死翘翘了,代码不好看。

同样是上面的那个com,样例代码:
public void run() {
    Dispatch test = new Dispatch("MyCOM.Test");
    MyCOMEvent myCOMEvent = new MyCOMEvent();
    DispatchEvents de = new DispatchEvents(test, myCOMEvent);
     Dispatch.call(test, "Add",90,68);
    Variant ret = Dispatch.call(test, "Sum", 3, 6);

    de.safeRelease();
    test.safeRelease();
}

可以看到jacob的调用方式,类似与我们通过反射方式获得实例的方法,然后在调用方法的过程。麻烦啊

选择三:Jacozoom
优点:使用方法和J-Integra for COM类似,一样的简单
缺点:和jacob一样的不稳定,仅仅是稍微好点,并发超过20个才崩溃,收费的。
样例代码懒得写了。

评价
没事就不要用java调com,再简单的代码也简单不错用c#调com,而且效率很有问题,调用10万次后计算出平均每次调用时间为1.7毫秒,这个效率实在太低了。
0 请登录后投票
   发表时间:2007-09-13  
谁说jni搞不定事件通知了?搞不定你列得这几个方案怎么实现的?SWT怎么实现的?只是你不会用罢了。
0 请登录后投票
   发表时间:2007-09-13  
rehte 写道
谁说jni搞不定事件通知了?搞不定你列得这几个方案怎么实现的?SWT怎么实现的?只是你不会用罢了。


好,请给个例子
0 请登录后投票
   发表时间:2007-09-13  
给个什么例子?
给个实现JNI事件通知的例子?
SWT的实现以及你列的都是使用JNI实现的
还有AWT/Swing的事件循环系统也是这样的
0 请登录后投票
   发表时间:2007-09-13  
对,就是给个实现JNI事件通知的例子. 象楼主一样,象我一样,给出真实、运行过代码。别光说,但又拿不出证明。

顺便补充一下上面我的例子中其他语言调用COM的代码。以下代码可以看到C#调用COM的代码比java的简单多了,就算是不会的人也猜得出这个com其实就是通过add方法传入两个整数,然后在事件相应中吧两个两个整数的处理结果输出。属于异步调用过程,上面例子中的main和disp_result在分别在两个线程中执行。

结论还是:JAVA调COM太麻烦了

VC#2005测试代码
using System;
using System.Collections.Generic;
using System.Text;

using sample3Lib;

namespace CSClient
{
    class Program
    {
        static void evtProcess(int rst)
        {
            Console.WriteLine(rst);
        }

        static void Main(string[] args)
        {
            DispConnectClass disp = new DispConnectClass();
            disp.Result += new _IDispConnectEvents_ResultEventHandler(disp_Result);
            disp.Add(1, 2);            
        }

        static void disp_Result(int nVal)
        {
            Console.WriteLine(nVal);
        }
    }
}



顺便补充一下COM的IDL
import "oaidl.idl";
import "ocidl.idl";

[
	object,
	uuid(B2584167-40E5-413A-85D3-056CC6AA4057),
	helpstring("IDispConnect 接口"),
	pointer_default(unique)
]
interface IDispConnect : IUnknown{
	[, helpstring("方法Add")] HRESULT Add([in] LONG n1, [in] LONG n2);
};
[
	object,
	uuid(E38136E3-E271-46F2-B460-CF43A2A5BC1D),
	dual,
	nonextensible,
	helpstring("IEvent2 接口"),
	pointer_default(unique)
]
interface IEvent2 : IDispatch{
	[id(1), helpstring("方法Multiply")] HRESULT Multiply([in] LONG n1, [in] LONG n2);
};
[
	uuid(35CE13A7-14A1-4493-A16A-FEBD4843AED2),
	version(1.0),
	helpstring("sample3 1.0 类型库")
]
library sample3Lib
{
	importlib("stdole2.tlb");
	[
		uuid(32A65970-38E7-47A8-A923-3C61F60D362C),
		helpstring("_IDispConnectEvents 接口")
	]
	dispinterface _IDispConnectEvents
	{
		properties:
		methods:
			[id(1), helpstring("方法Result")] HRESULT Result([in] LONG nVal);
	};
	[
		uuid(85BC3789-164A-4BF0-A206-7833A832F6A8),
		helpstring("DispConnect Class")
	]
	coclass DispConnect
	{
		[default] interface IDispConnect;
		[default, source] dispinterface _IDispConnectEvents;
	};
	[
		uuid(D58AF39C-DA5C-47E1-AB40-C86FC61A2F19),
		helpstring("_IEvent2Events 接口")
	]
	dispinterface _IEvent2Events
	{
		properties:
		methods:
			[id(1), helpstring("方法Result")] HRESULT Result([in] LONG nVal);
	};
	[
		uuid(1DF179A6-4560-4364-8102-01F8713534C8),
		helpstring("Event2 Class")
	]
	coclass Event2
	{
		[default] interface IEvent2;
		[default, source] dispinterface _IEvent2Events;
	};
};
0 请登录后投票
   发表时间:2007-09-13  
JAVA调COM太麻烦了,这个我承认啊。但我反驳的是你的jni不能搞定事件通知的论调。你自己举的解决java com的解决方案已经反驳了自己,我举的证据SWT/AWT/Swing的事件系统也是证据。
我没有义务向你提供任何证明代码,也没有必要去证明。如果你想弄明白,自己去学习它们的代码。
0 请登录后投票
   发表时间:2007-09-13  
 这帖子也就说了java如何调用本地native代码,和com一点边都搭不上.连IUnknown都没有出现

0 请登录后投票
   发表时间:2007-09-13  
rehte 写道
JAVA调COM太麻烦了,这个我承认啊。但我反驳的是你的jni不能搞定事件通知的论调。你自己举的解决java com的解决方案已经反驳了自己,我举的证据SWT/AWT/Swing的事件系统也是证据。
我没有义务向你提供任何证明代码去,也没有必要去证明去。如果你想弄明白,自己去学习它们的代码去。


--! COM事件和SWT/AWT/Swing的事件系统原理类似,但在实现上差别太大了.

说实话,要白手起家把Java和com串起来,问题不在接口,而在于要用c写一堆莫名其妙的东西.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics