当前位置:编程学习 > JAVA >>

如何处理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

/* 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
--------------------编程问答-------------------- AD12SUSB.cpp

#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
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,