线程“main”中的Expect java.lang.UnsatisfiedLinkError:JNItest2.helloworld()V

时间:2017-03-31 11:47:53

标签: java java-native-interface

我在ubuntu的test.cpp中创建了libcc.so,并使用指令ldd来检查它与opencv2.4.2,ffmpeg0.11.1和其他链接没有问题。

但是当我尝试使用eclipse加载libcc.so时,我收到错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: JNItest2.helloworld()V
at JNItest2.helloworld(Native Method)
at JNItest2.main(JNItest2.java:28)

Java代码:

public class JNItest2 {
  public native void helloworld();
  static{   
      String libPath= "/home/sun/workspace/JNItest2/src";
      System.setProperty("java.library.path",libPath);
      String Path = System.getProperty("java.library.path");
      System.out.println("java.library.path=" + Path);
      System.loadLibrary("cc");         
  }
  public static void main(String[] args){        
     new JNItest2().helloworld();
  }
}

.h代码:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNItest2 */

#ifndef _Included_JNItest2
#define _Included_JNItest2
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNItest2
 * Method:    helloworld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JNItest2_helloworld
  (JNIEnv *, jobject);    

#ifdef __cplusplus
}
#endif
#endif

TEST.CPP

#include <jni.h>
#include "JNItest2.h"
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <vector>
#include <list>
#include <string>
IplImage* image = 0; 
IplImage* prev_image = 0;
CvCapture* capture = 0;
JNIEXPORT void JNICALL
Java_JNItest2_helloworld(JNIEnv *env,jobject object,int argc,char ** argv)
{
    signal(SIGSEGV,sighandler);
    int frameNum = 0;
    char* video=null;
    char* video = argv[1];
    capture = cvCreateFileCapture(video);
    if( !capture ) { 
        printf( "Could not initialize capturing..\n" );
        return ;
    }
    while(true) 
    {
        frameNum += 1;
        IplImage* frame = 0;
        int i, j, c;    

        frame = cvQueryFrame( capture );
        if( !frame )
            break;    

        if( !image ) {
            image =  cvCreateImage( cvSize(frame->width,frame->height), 8, 3);
            image->origin = frame->origin;
        }    

        cvCopy( frame, image, 0 );
        std::cerr << "The " << frameNum << "-th frame" << std::endl;
        frameNum++;
    }    

    return;
}

我在网上搜索了很长时间。但我无法解决我的问题。请帮忙或尝试给我一些想法。

2 个答案:

答案 0 :(得分:0)

您声明了此功能:

JNIEXPORT void JNICALL Java_JNItest2_helloworld
  (JNIEnv *, jobject); 

但你实现了这个:

JNIEXPORT void JNICALL
Java_JNItest2_helloworld(JNIEnv *env,jobject object,int argc,char ** argv)

确保:

JNIEXPORT void JNICALL
Java_JNItest2_helloworld(JNIEnv *env,jobject object)

在您的cpp代码中。

答案 1 :(得分:0)

.h文件中的签名与.cpp文件中的签名不符。

JNIEXPORT void JNICALL Java_JNItest2_helloworld(JNIEnv *, jobject);    

JNIEXPORT void JNICALL Java_JNItest2_helloworld(JNIEnv *env,jobject object,int argc,char ** argv)

您尝试调用的方法是头文件中的方法。但它缺少实施。

如果您想将参数传递给C方,则必须使用native方法声明它们:

public native void helloworld(String[] args);

结果签名将是:

JNIEXPORT void JNICALL Java_Main_helloworld(JNIEnv *, jobject, jobjectArray);

但是此String[]未转换为argcargv,您必须使用JNI api手动执行此操作:

#include <stdio.h>
#include <stdlib.h>

JNIEXPORT void JNICALL Java_Main_helloworld(JNIEnv *env, jobject o, jobjectArray args) {
    int argc = (*env)->GetArrayLength(env, args);   
    const char* argv[argc];

    // convert String[] to const char**
    for(int i = 0; i < argc; i++) {
        jstring string = (jstring) (*env)->GetObjectArrayElement(env, args, i);
        int slength = (*env)->GetStringLength(env, string);
        const wchar_t* wchars = (*env)->GetStringChars(env, string, NULL);

        argv[i] = malloc(slength + 1); // + 1 for terminator
        wcstombs(argv[i], wchars, slength + 1);

        (*env)->ReleaseStringChars(env, string, wchars);
    }

    // use argc and argv
}