如何处理java.lang.UnsatisfiedLinkError?
用jcc生成DLL,包装另一个C++的DLL,当Java源文件在默认包中时,对DLL的调用正常;现在将Java源文件放在一个包中,重复上面的过程,
生成的DLL调用时产生java.lang.UnsatisfiedLinkError: com.xji.jni.AD12SUSB.setCCDParameter(IJ)I
用dllexp.exe察看DLL文件的内容,发现方法名有一个前缀:_Z36,全名如下:
_Z36Java_com_xji_jni_AD12SUSB_closeBoardP7JNIEnv_P8_jobject
对照默认包中能正常使用的DLL文件:
Java_AD12SUSB_closeBoard
请问:如何去掉_Z36Java_com_xji_jni_AD12SUSB_closeBoardP7JNIEnv_P8_jobject中的前缀和后缀?
或者如何能正确调用该DLL文件?
--------------------编程问答-------------------- --------------------编程问答-------------------- com_xji_jni_AD12SUSB.h
--------------------编程问答-------------------- AD12SUSB.cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xji_jni_AD12SUSB */
#ifndef _Included_com_xji_jni_AD12SUSB
#define _Included_com_xji_jni_AD12SUSB
#ifdef __cplusplus
extern "C" {
#endif
#undef com_xji_jni_AD12SUSB_CCD_INTEGRAL
#define com_xji_jni_AD12SUSB_CCD_INTEGRAL 1L
#undef com_xji_jni_AD12SUSB_CCD_PIXEL_SLT
#define com_xji_jni_AD12SUSB_CCD_PIXEL_SLT 2L
#undef com_xji_jni_AD12SUSB_CCD_FREQUENCY
#define com_xji_jni_AD12SUSB_CCD_FREQUENCY 3L
#undef com_xji_jni_AD12SUSB_CCD_PIXELS
#define com_xji_jni_AD12SUSB_CCD_PIXELS 2048L
/*
* Class: com_xji_jni_AD12SUSB
* Method: setCCDParameter
* Signature: (IJ)I
*/
JNIEXPORT jint JNICALL Java_com_xji_jni_AD12SUSB_setCCDParameter
(JNIEnv *, jclass, jint, jlong);
/*
* Class: com_xji_jni_AD12SUSB
* Method: acquisitionData
* Signature: ([S)I
*/
JNIEXPORT jint JNICALL Java_com_xji_jni_AD12SUSB_acquisitionData
(JNIEnv *, jclass, jshortArray);
/*
* Class: com_xji_jni_AD12SUSB
* Method: closeBoard
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_xji_jni_AD12SUSB_closeBoard
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include <windows.h>
#include <windef.h>
#include <string.h>
#include "dllkxusb.h"
#include "AD12SUSB.h"
//调试预处理语句
//#define DEBUG_AD12SUSB
//将本地函数包装成一个函数:采集函数,所有操作集中处理,使用静态变量保存状态
//2012-4-13 2013-4-17
typedef DWORD
(WINAPI * DATAACQ) ( HANDLE hBoard, PVOID Data ); //声明函数指针类型
typedef BOOL
(WINAPI * SETCCDPARAM) ( HANDLE hBoard, WORD wParam, long lParam ); //声明函数指针类型
typedef void
(WINAPI * CLOSEBOARD) ( HANDLE hBoard ); //声明函数指针类型
static DATAACQ pDataAcquisition = NULL; //声明函数指针
static SETCCDPARAM pSetCcdParam = NULL; //声明函数指针
static CLOSEBOARD pCloseBoard = NULL; //声明函数指针
static HINSTANCE dllHandle = NULL; //声明句柄
static BOOL hadAcqBoard = 0; //找到采集卡
static BOOL openedAcqBoard = 0; //已经打开采集卡
static HANDLE hBoard = NULL; //采集卡句柄
static DEVICE_LOCATION Device [ 32 ]; //结构数组
static WORD wDaqData [ 2048 ];
int
AD12SUSB_prepare ( void )
{
//加载动态链接库
if ( dllHandle == NULL ) //未加载动态链接库
{
dllHandle = LoadLibrary ( "dllkxusb.dll" ); //加载动态链接库
if ( dllHandle == NULL )
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "加载动态链接库失败!dllkxusb.dll" );
#endif
return 1; //操作失败
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "已加载动态链接库dllkxusb.dll" );
#endif
}
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "已加载动态链接库dllkxusb.dll" );
#endif
}
//查找采集卡
if ( !hadAcqBoard ) //未找到采集卡
{
typedef int
(WINAPI * DEVICEFIND) ( PDEVICE_LOCATION pDevice ); //声明函数指针类型
DEVICEFIND pDeviceFind; //声明函数指针
//获取函数指针:函数名称使用eXeScope.exe查看dllkxusb.dll,确定函数名的变异
pDeviceFind = ( DEVICEFIND ) GetProcAddress ( dllHandle, "_lcDeviceFind@4" ); //函数指针指向lcDeviceFind
if ( pDeviceFind ) //成功获取函数指针
{
int temp;
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcDeviceFind" );
#endif
temp = pDeviceFind ( Device ); //执行函数
if ( temp == 0 ) //没有采集卡
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未找到采集卡!" );
#endif
return 1; //操作失败
}
else //有采集卡
{
hadAcqBoard = 1;
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "找到采集卡!" );
#endif
}
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未捕获函数lcDeviceFind" );
#endif
return 1; //操作失败
}
}
else //找到采集卡
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "找到采集卡!" );
#endif
}
//打开采集卡
if ( !openedAcqBoard ) //未打开采集卡
{
typedef HANDLE
(WINAPI * OPENBOARD) ( int nDevIndex ); //声明函数指针类型
OPENBOARD pOpenBoard; //声明函数指针
//获取函数指针:函数名称使用eXeScope.exe查看dllkxusb.dll,确定函数名的变异
pOpenBoard = ( OPENBOARD ) GetProcAddress ( dllHandle, "_lcOpenBoard@4" ); //函数指针指向lcOpenBoard
if ( pOpenBoard ) //成功获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcOpenBoard" );
#endif
hBoard = pOpenBoard ( 0 ); //执行函数,打开0#采集卡
if ( hBoard == NULL )
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未打开采集卡!" );
#endif
return 1; //操作失败
}
else
{
openedAcqBoard = 1;
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "已打开采集卡!" );
#endif
}
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未捕获函数lcDeviceFind" );
#endif
return 1; //操作失败
}
}
else //已打开采集卡
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "已打开采集卡!" );
#endif
}
return 0; //操作成功
}
// 采集卡参数设置 BOOL WINAPI lcSetCCDParam(HANDLE hBoard, WORD wParam, long lParam);
JNIEXPORT jint JNICALL
Java_com_xji_jni_AD12SUSB_setCCDParameter ( JNIEnv *env, jobject obj, jint wParam, jlong lParam )
{
BOOL bl = 0;
// 查找并打开采集卡
if ( AD12SUSB_prepare () ) //操作失败
{
return 1; //操作失败
}
// 设置参数
if ( pSetCcdParam == NULL ) //未获取函数指针
{
//获取函数指针:函数名称使用eXeScope.exe查看dllkxusb.dll,确定函数名的变异
pSetCcdParam = ( SETCCDPARAM ) GetProcAddress ( dllHandle, "_lcSetCCDParam@12" ); //函数指针指向lcSetCCDParam
if ( pSetCcdParam ) //成功获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcSetCCDParam" );
#endif
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未捕获函数lcDataAcquisition" );
#endif
return 1; //操作失败
}
}
if ( pSetCcdParam ) //成功获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcSetCCDParam" );
#endif
bl = pSetCcdParam ( hBoard, wParam, lParam ); //执行函数
if ( bl == 0 ) //参数设置失败
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "参数设置失败!" );
#endif
return 1; //操作失败
}
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "参数设置成功!" );
switch ( wParam )
{
case 1:
printf ( "%s", "CCD积分时间设置为 " );
printf ( "%d", ( int ) lParam );
printf ( "%s\n", "档。" );
break;
case 2:
printf ( "%s", "CCD像元设置为 " );
printf ( "%d", ( int ) lParam );
printf ( "%s\n", "个。" );
break;
case 3:
printf ( "%s", "CCD驱动频率设置为 " );
printf ( "%d", ( int ) lParam );
printf ( "%s\n", "档。" );
break;
default:
break;
}
#endif
return 0; //操作成功
}
}
JNIEXPORT jint JNICALL
Java_com_xji_jni_AD12SUSB_acquisitionData ( JNIEnv *env, jobject obj, jshortArray sarr )
{
int temp;
// 查找并打开采集卡
if ( AD12SUSB_prepare () ) //操作失败
{
return 1; //操作失败
}
// 采集数据
if ( pDataAcquisition == NULL ) //未获取函数指针
{
//获取函数指针:函数名称使用eXeScope.exe查看dllkxusb.dll,确定函数名的变异
pDataAcquisition = ( DATAACQ ) GetProcAddress ( dllHandle, "_lcDataAcquisition@8" ); //函数指针指向lcDataAcquisition
if ( pDataAcquisition ) //成功获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcDataAcquisition" );
#endif
temp = 1;
temp = ( jint ) pDataAcquisition ( hBoard, wDaqData ); //执行函数
}
else
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未捕获函数lcDataAcquisition" );
#endif
return 1; //操作失败
}
}
else
{
temp = 1;
temp = ( jint ) pDataAcquisition ( hBoard, wDaqData ); //执行函数
}
if ( temp == 0 ) //采集成功
{
#ifdef DEBUG_AD12SUSB
printf ( "%d%s%d\n", hBoard, "数据采集成功! temp=", temp );
for ( short i = 0; i < 10; i += 5 )
{
printf ( "%s", "wD_" );
printf ( "%d ", i );
printf ( "%d\t", wDaqData [ i ] );
printf ( "%s", "wD_" );
printf ( "%d ", i + 1 );
printf ( "%d\t", wDaqData [ i + 1 ] );
printf ( "%s", "wD_" );
printf ( "%d ", i + 2 );
printf ( "%d\t", wDaqData [ i + 2 ] );
printf ( "%s", "wD_" );
printf ( "%d ", i + 3 );
printf ( "%d\t", wDaqData [ i + 3 ] );
printf ( "%s", "wD_" );
printf ( "%d ", i + 4 );
printf ( "%d\n", wDaqData [ i + 4 ] );
}
#endif
jsize start = 0;
jsize stop = 2048;
env->SetShortArrayRegion ( sarr, 0, 2048, ( jshort* ) wDaqData ); //复制数据到JAVA数组
}
else //采集失败
{
#ifdef DEBUG_AD12SUSB
printf ( "%d%s%d\n", hBoard, "数据采集失败! temp=", temp );
#endif
return 1; //操作失败
}
return 0; //操作成功
}
// 关闭采集卡 void WINAPI lcCloseBoard(HANDLE hBoard);
JNIEXPORT jint JNICALL
Java_com_xji_jni_AD12SUSB_closeBoard ( JNIEnv *env, jobject obj )
{
if ( openedAcqBoard == 0 ) //未打开采集卡
{
return 1; //未打开采集卡
}
if ( pCloseBoard == NULL ) //未获取函数指针
{
pCloseBoard = ( CLOSEBOARD ) GetProcAddress ( dllHandle, "_lcCloseBoard@4" ); //函数指针指向lcCloseBoard
if ( pCloseBoard == NULL ) //未获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未捕获函数lcCloseBoard" );
#endif
return 2; //未获取函数指针
}
}
if ( pCloseBoard ) //已获取函数指针
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "捕获函数lcCloseBoard" );
#endif
if ( hBoard == NULL )
{
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "未打开采集卡!" );
#endif
return 1; //未打开采集卡
}
else
{
pCloseBoard ( hBoard ); //执行函数
FreeLibrary ( dllHandle ); //释放动态链接库
#ifdef DEBUG_AD12SUSB
printf ( "%s\n", "已关闭采集卡!" );
printf ( "%s\n", "已释放动态链接库dllkxusb.dll" );
#endif
return 0; //已关闭采集卡
}
}
}
//可行:gcc -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -Wl,--add-stdcall-alias -shared -o AD12SUSB.dll AD12SUSB.cpp
//可行:g++ -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -Istdc++ -Wl,--add-stdcall-alias -shared -o AD12SUSB.dll AD12SUSB.cpp
//不行:gcc -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -Wall -shared AD12SUSB.cpp -o AD12SUSB.dll
补充:Java , Java SE