Java如何通过VC调用VB编写的COM

    前几天,一位同事问起如何在java中调用vb写的com,以前知道可以用java的native方式,通过windows dll中转来实现,但未实践过,今天忙里偷闲,刚好试了一把。写了一个最简例子。
    步骤很简单,或许哪位同学以后有可能用到,俺就帮忙整理了一下:

第一步:生成最简COM(采用VB60)
1.1:VB代码
PROGID:testVBCom.clsTest
线程模型:STA 多实例模型
Public Function FuncTest(ByVal strInput As String, ByVal nInput As Long) As String
     FuncTest = "VBCom测试:" & strInput & CStr(nInput)
End Function
就这么简单,呵呵。

第二步:定义Native方法,导出Windows DLL的输出节声明(采用Eclipse3.1)
2.1 java代码:
package com.kingdee;
public class testCallNative {
  static
  {
    System.loadLibrary("CallComAPI");
  }
  public native String callAPI(String str1 ,int n);
  ……
}
2.2:导出声明
javah -jni com.kingdee.testCallNative
得到com_kingdee_testCallNative.h 文件
注:这属于java虚拟机调用与Windows dll的标准方式,从名称可看出端倪,不能更改约定的输出名,如此例的输出名称为:
JNIEXPORT jstring JNICALL Java_com_kingdee_testCallNative_callAPI
  (JNIEnv *, jobject, jstring, jint);

第三步:编写Windows DLL(采用VC6.0)
先说明一下,要编写Windows DLL,可以采用MFC或是SDK,为了更方便的访问Com,我的例子用了MFC,并用到部分ATL,但实际上可以采用最简SDK方式来实现。
3.1:生成API DLL框架
a:使用VC向导生成MFC方式的DLL(注意:是常规DLL,不能使用扩展方式)
b:定义def文件内容:
EXPORTS
   Java_com_kingdee_testCallNative_callAPI @1
c:包含上一步的.h文件。
d:在Path中或是VC的Option中添加必要的include目录。
比如:我的机器上是:
D:/Program Files/Java/jdk1.5.0/include
D:/Program Files/Java/jdk1.5.0/include/win32
e:添加实现过程名。
JNIEXPORT jstring JNICALL Java_com_kingdee_testCallNative_callAPI
  (JNIEnv * jEnv, jobject, jstring jsInput, jint jnInput)
{
   jstring jsRet;

   return jsRet;
}

3.2:实现com调用的代码。(采用#import方式调用标准com)
stdafx.h:
#include <atlbase.h>
#import "..//vbCom//testVBCom.dll" named_guids

CallComAPI.cpp
#include "com_kingdee_testCallNative.h"

void GetJString(JNIEnv * jEnv,LPCTSTR lpszBuffer,jstring & js)
{
    USES_CONVERSION;
    LPWSTR pw = T2W(lpszBuffer);
    js = jEnv->NewString(pw,wcslen(pw));
    return;
}

JNIEXPORT jstring JNICALL Java_com_kingdee_testCallNative_callAPI
  (JNIEnv * jEnv, jobject, jstring jsInput, jint jnInput)
{
    ::CoInitialize(NULL);

    //convert input params
    CString sInput = jEnv->GetStringUTFChars(jsInput,0);

    CString sRet;
    testVBCom::_clsTest *pTest = NULL;
    jstring jsRet;
    try
    {
        //get com's interface
        if( FAILED(::CoCreateInstance(testVBCom::CLSID_clsTest,NULL,CLSCTX_INPROC,
               testVBCom::IID__clsTest,(LPVOID*)&pTest)) )
            throw(_T("Get com's interface failed!"));

       //call com's method
       _bstr_t bstr1(sInput);
       bstr1 = pTest->FuncTest(bstr1,jnInput);
       sRet = bstr1.copy();

       GetJString(jEnv,sRet,jsRet);
    }
    catch (LPCTSTR lpszErr)
    {
       GetJString(jEnv,lpszErr,jsRet);
    }
    catch(...)
    {
       GetJString(jEnv,_T("Unknown error!"),jsRet);
    }
    if(pTest) pTest->Release();
    ::CoUninitialize();
    return jsRet;
}

第四步:编写java的测试(用Eclipse 3.1)
4.1:添加Native的相关路径:
我机器上的路径是:
-Djava.library.path=E:/work/CallComForJava/example/CallComAPI/Release

4.2:测试代码:
public static void main(String[] args) {
    System.out.println("Start...");
    testCallNative testObj = new testCallNative();
    System.out.println(testObj.callAPI("test",1));
    System.out.println("End...");
}

4.3:运行
得到结果:
Start...
VBCom测试:test1
End...

简单吧,嘿嘿。

注意事项:
1:采用VC6.0编写的Debug版的DLL不能被java正常调用,原因不详,必须用Release版。
2:在API中进行控制台输出时,其次序并不如想象。
如在API中一头一尾加上:
printf("/napi dll start...");
……
printf("/napi dll ebd...");

运行,在控制台的输出是:
Start...
VBCom测试:test1
End...
api dll start...
api dll end...

石头 于2005-11-16

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值