您的位置:首页 > 编程语言 > Delphi

Java调用Delphi DLL(通过C++调用和直接调用两种方式)

2009-05-05 15:58 801 查看
文章来自[SVN中文技术网]转发请保留本站地址:http://www.svn8.com/java/Socket/20080924/1002.html

文章摘要:关于Delphi的DLL,先前在VC,VB,PB这些开发工具中调用都是没有问题的,但是在Java中还没有做过,于是Google,据说是直接调可能有问题,最好在中间用C++转一下。

一、Java->C++->Delphi
1、Delphi中的代码很简单:
function search(name: pchar): pchar; stdcall;
begin
result := pchar('hello '+name);
end;

exports
search index 1;

2、Java中新建一个类DllTest
public class DllTest {
public native static String get(String name);
static {
System.loadLibrary("DllTest");
}

public static void main(String[] args) {
//TODO ...
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(jdkinclude),jni_md.h(jdkincludewin32),StdAfx.h(代码后附)都拷到DllTest目录下面,
DllTest.h的代码如下:
-----------------------------------------------------------------------------------------------------
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class DllTest */

#ifndef _Included_DllTest
#define _Included_DllTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: DllTest
* Method: get
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_DllTest_get (JNIEnv *, jclass, jstring Name);

#ifdef __cplusplus
}
#endif
#endif

StdAfx.h代码如下:
-----------------------------------------------------------------------------------------------------
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#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

// Insert your headers here
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <windows.h>

// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#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 )
{
/* AFX_MANAGE_STATE(AfxGetStaticModuleState()); */
jstring rtn = 0;
int slen = strlen(str);
wchar_t* buffer = 0;
if( slen == 0 )
rtn = env->NewStringUTF(str); //UTF ok since empty string
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;
}

// This is an example of an exported function.
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);
FreeLibrary(hDLL);
return env->NewStringUTF(ret);
//return windowsToJstring(env,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;
}
}
}
}
这样也是调用成功的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: