您的位置:首页 > 编程语言 > Java开发

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

2005-11-16 21:21 639 查看
前几天,一位同事问起如何在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: