|
这段时间客户在上一个触摸屏查询的项目,这个项目是包给另一个公司做的,但里面的一些业务逻辑需要用到我们原有的一个DLL,于是就有了这次Java和Delphi的邂逅。。。
关于Delphi的DLL,先前在VB、PB这些开发工具中调用都是没有问题的,但是在Java中还没有做过,于是先请教了一下Mr Google,据说是直接调可能有问题,最好在中间用C++转一下,下面就先讲Java->C++->Delphi这种方法:
一、Java->C++->Delphi
1、Delphi中的代码很简单:
- function search(name: pchar): pchar; stdcall;
- begin
- result := pchar('hello '+name);
- end;
- exports
- search;
2、Java中新建一个类DllTest
- public class DllTest {
- public native static String get(String name);
-
- static {
- System.loadLibrary("DllTest");
- }
-
- public static void main(String[] args) {
-
- DllTest test = new DllTest();
- String ret = test.get("yf");
- System.out.println(ret);
- System.out.println("success!!");
- }
- }
编译生成class文件后,到命令行,该文件所在目录
javah -classpath . -jni DllTest
生成DllTest.h头文件,这个在C++中要用的
3、接下来就该C++出场了
首先在C++中新建一个DLL的工程DllTest,接着把刚才生成的DllTest.h、jni.h(jdk\include\)、jni_md.h(jdk\include\win32\)、StdAfx.h(代码后附)都拷到DllTest目录下面,DllTest.h的代码如下:
-
- #include "jni.h"
-
- #ifndef _Included_DllTest
- #define _Included_DllTest
- #ifdef __cplusplus
- extern "C" {
- #endif
-
-
-
-
-
- JNIEXPORT jstring JNICALL Java_DllTest_get
- (JNIEnv *, jclass, jstring Name);
- #ifdef __cplusplus
- }
- #endif
- #endif
StdAfx.h代码如下:
- #if !defined(AFX_STDAFX_H__AEAE6431_AB02_4D9C_84D7_11491AAF82FF__INCLUDED_)
- #define AFX_STDAFX_H__AEAE6431_AB02_4D9C_84D7_11491AAF82FF__INCLUDED_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
- #include <windows.h>
- #endif // !defined(AFX_STDAFX_H__AEAE6431_AB02_4D9C_84D7_11491AAF82FF__INCLUDED_)
新建一个DT.cpp文件,代码如下:
- #include "StdAfx.h"
- #include "stdlib.h"
- #include "DllTest.h"
- HINSTANCE hDLL;
- typedef char* (__stdcall *SEARCH)(const char* name);
- SEARCH search;
- jstring windowsToJstring( JNIEnv* env, const char* str )
- {
-
- jstring rtn = 0;
- int slen = strlen(str);
- wchar_t* buffer = 0;
- if( slen == 0 )
- rtn = env->NewStringUTF(str);
- else
- {
- int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
- buffer = (wchar_t*)malloc( length*2 + 1 );
- if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
- rtn = env->NewString( (jchar*)buffer, length );
- }
- if( buffer )
- free( buffer );
- return rtn;
- }
- jstring JNICALL Java_DllTest_get(JNIEnv *env, jobject cl, jstring Name)
- {
- char buf[6]= "error";
- const char* name;
- const char* ret;
- name = env->GetStringUTFChars(Name, NULL);
- jstring err = env->NewStringUTF(buf);
-
- if (NULL == (hDLL = LoadLibrary("simple.dll"))){
- MessageBox(0,"Error to load simple.dll!","标题",MB_OKCANCEL );
- return err;
- }
- search = (SEARCH)GetProcAddress(HMODULE(hDLL),"search");
- if (FARPROC(search) == FARPROC(NULL)){
- MessageBox(0,"Error to get procedure's address!","标题",MB_OKCANCEL );
- return err;
- }
- ret = search(name);
- return env->NewStringUTF(ret);
- }
windowsToJstring这个函数是为了解决中文乱码的问题
用Release生产DllTest.dll文件,并拷贝到jdk的bin目录,就可以用DllTest.class测试了;
二、Java->Delphi
之后,又发现直接调也可以成功,不解。。。
Delphi的Dll还是同一个,另外还需要JNativeCpp.dll和JNative.jar
Java的代码修改如下:
- public static void main(String[] args) {
- TestNative test = new TestNative();
- JNative jn = null;
- String str = "";
- try {
- jn = new JNative("simple","search");
- jn.setRetVal(Type.STRING);
- jn.setParameter(0,Type.STRING,"yf");
- jn.invoke();
- str = jn.getRetVal();
- System.out.println(str);
- } catch (NativeException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }finally{
- if(null != jn){
- try {
- jn.dispose();
- jn = null;
- } catch (NativeException e) {
- jn = null;
- } catch (IllegalAccessException e) {
- jn = null;
- }
- }
- }
- }
这样也是调用成功的!
|