2014-07-25 64 views
0

我想爲庫編寫C++綁定,所以爲了學習,我使用了以下簡單的java和C++代碼。我正在使用SWIG。Eclipse + JNI:可以找到庫,但不是方法

Java代碼:

public class App { 

    static{ 
     System.loadLibrary("demo"); 
    } 

    public static void main(String[] args) { 

     // TODO Auto-generated method stub 
     System.out.println(System.getProperty("java.library.path")); 
     printHello("Lars"); 
    } 

    native static void printHello(String name); 
} 

我的C++代碼:

#include <iostream> 
#include <string> 
#include "demo.hpp" 

void printHello(std::string name){ 
    std::cout << "Hello: "<< name << "\n"; 
} 

我的報頭:

void printHello(std::string); 

爲SWIG的.i文件:

%module demo 
%include "std_string.i" 
%{ 
    #include <iostream> 
    #include <string> 
    #include "demo.hpp" 
%} 
    extern void printHello(std::string); 

我跑swig -C++ -java demo.i沒有問題。 編譯:

g++ -c -fPIC demo_wrap.cxx -I/usr/lib64/jvm/java-1.7.0-openjdk-1.7.0/include/ -I/usr/lib64/jvm/java-1.7.0-openjdk-1.7.0/include/linux 

並取得共享庫,並移動到/ usr/lib目錄

g++ -shared demo_wrap.o -o libdemo.so 

但後來我試着使用,Eclipse來運行我的java程序,我得到這個錯誤:

Exception in thread "main" java.lang.UnsatisfiedLinkError: App.printHello(Ljava/lang/String;)V 
    at App.printHello(Native Method) 
    at App.main(App.java:11) 

所以從我所知道的,eclipse/java知道我的庫存在,但它無法在庫中找到我的函數/方法。 有什麼我做錯了嗎?或者我錯過了什麼?

由於它推進

編輯:如果demoJNI.java的內容可能會幫助

public class demoJNI { 
    public final static native void printHello(String jarg1); 
} 

Demo_wrap.cxx

/* ---------------------------------------------------------------------------- 
* This file was automatically generated by SWIG (http://www.swig.org). 
* Version 2.0.10 
* 
* This file is not intended to be easily readable and contains a number of 
* coding conventions designed to improve portability and efficiency. Do not make 
* changes to this file unless you know what you are doing--modify the SWIG 
* interface file instead. 
* ----------------------------------------------------------------------------- */ 

#define SWIGJAVA 


#ifdef __cplusplus 
/* SwigValueWrapper is described in swig.swg */ 
template<typename T> class SwigValueWrapper { 
    struct SwigMovePointer { 
    T *ptr; 
    SwigMovePointer(T *p) : ptr(p) { } 
    ~SwigMovePointer() { delete ptr; } 
    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } 
    } pointer; 
    SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs); 
    SwigValueWrapper(const SwigValueWrapper<T>& rhs); 
public: 
    SwigValueWrapper() : pointer(0) { } 
    SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } 
    operator T&() const { return *pointer.ptr; } 
    T *operator&() { return pointer.ptr; } 
}; 

template <typename T> T SwigValueInit() { 
    return T(); 
} 
#endif 

/* ----------------------------------------------------------------------------- 
* This section contains generic SWIG labels for method/variable 
* declarations/attributes, and other compiler dependent labels. 
* ----------------------------------------------------------------------------- */ 

/* template workaround for compilers that cannot correctly implement the C++ standard */ 
#ifndef SWIGTEMPLATEDISAMBIGUATOR 
# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) 
# define SWIGTEMPLATEDISAMBIGUATOR template 
# elif defined(__HP_aCC) 
/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ 
/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ 
# define SWIGTEMPLATEDISAMBIGUATOR template 
# else 
# define SWIGTEMPLATEDISAMBIGUATOR 
# endif 
#endif 

/* inline attribute */ 
#ifndef SWIGINLINE 
# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) 
# define SWIGINLINE inline 
# else 
# define SWIGINLINE 
# endif 
#endif 

/* attribute recognised by some compilers to avoid 'unused' warnings */ 
#ifndef SWIGUNUSED 
# if defined(__GNUC__) 
# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) 
#  define SWIGUNUSED __attribute__ ((__unused__)) 
# else 
#  define SWIGUNUSED 
# endif 
# elif defined(__ICC) 
# define SWIGUNUSED __attribute__ ((__unused__)) 
# else 
# define SWIGUNUSED 
# endif 
#endif 

#ifndef SWIG_MSC_UNSUPPRESS_4505 
# if defined(_MSC_VER) 
# pragma warning(disable : 4505) /* unreferenced local function has been removed */ 
# endif 
#endif 

#ifndef SWIGUNUSEDPARM 
# ifdef __cplusplus 
# define SWIGUNUSEDPARM(p) 
# else 
# define SWIGUNUSEDPARM(p) p SWIGUNUSED 
# endif 
#endif 

/* internal SWIG method */ 
#ifndef SWIGINTERN 
# define SWIGINTERN static SWIGUNUSED 
#endif 

/* internal inline SWIG method */ 
#ifndef SWIGINTERNINLINE 
# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE 
#endif 

/* exporting methods */ 
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 
# ifndef GCC_HASCLASSVISIBILITY 
# define GCC_HASCLASSVISIBILITY 
# endif 
#endif 

#ifndef SWIGEXPORT 
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) 
# if defined(STATIC_LINKED) 
#  define SWIGEXPORT 
# else 
#  define SWIGEXPORT __declspec(dllexport) 
# endif 
# else 
# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) 
#  define SWIGEXPORT __attribute__ ((visibility("default"))) 
# else 
#  define SWIGEXPORT 
# endif 
# endif 
#endif 

/* calling conventions for Windows */ 
#ifndef SWIGSTDCALL 
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) 
# define SWIGSTDCALL __stdcall 
# else 
# define SWIGSTDCALL 
# endif 
#endif 

/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ 
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) 
# define _CRT_SECURE_NO_DEPRECATE 
#endif 

/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ 
#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) 
# define _SCL_SECURE_NO_DEPRECATE 
#endif 



/* Fix for jlong on some versions of gcc on Windows */ 
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) 
    typedef long long __int64; 
#endif 

/* Fix for jlong on 64-bit x86 Solaris */ 
#if defined(__x86_64) 
# ifdef _LP64 
# undef _LP64 
# endif 
#endif 

#include <jni.h> 
#include <stdlib.h> 
#include <string.h> 


/* Support for throwing Java exceptions */ 
typedef enum { 
    SWIG_JavaOutOfMemoryError = 1, 
    SWIG_JavaIOException, 
    SWIG_JavaRuntimeException, 
    SWIG_JavaIndexOutOfBoundsException, 
    SWIG_JavaArithmeticException, 
    SWIG_JavaIllegalArgumentException, 
    SWIG_JavaNullPointerException, 
    SWIG_JavaDirectorPureVirtual, 
    SWIG_JavaUnknownError 
} SWIG_JavaExceptionCodes; 

typedef struct { 
    SWIG_JavaExceptionCodes code; 
    const char *java_exception; 
} SWIG_JavaExceptions_t; 


static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { 
    jclass excep; 
    static const SWIG_JavaExceptions_t java_exceptions[] = { 
    { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, 
    { SWIG_JavaIOException, "java/io/IOException" }, 
    { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, 
    { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, 
    { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, 
    { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, 
    { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, 
    { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, 
    { SWIG_JavaUnknownError, "java/lang/UnknownError" }, 
    { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } 
    }; 
    const SWIG_JavaExceptions_t *except_ptr = java_exceptions; 

    while (except_ptr->code != code && except_ptr->code) 
    except_ptr++; 

    jenv->ExceptionClear(); 
    excep = jenv->FindClass(except_ptr->java_exception); 
    if (excep) 
    jenv->ThrowNew(excep, msg); 
} 


/* Contract support */ 

#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else 


#include <string> 


    #include <iostream> 
    #include <string> 
    #include "demo.hpp" 


#ifdef __cplusplus 
extern "C" { 
#endif 

SWIGEXPORT void JNICALL Java_demoJNI_printHello(JNIEnv *jenv, jclass jcls, jstring jarg1) { 
    std::string arg1 ; 

    (void)jenv; 
    (void)jcls; 
    if(!jarg1) { 
    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); 
    return ; 
    } 
    const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); 
    if (!arg1_pstr) return ; 
    (&arg1)->assign(arg1_pstr); 
    jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); 
    printHello(arg1); 
} 


#ifdef __cplusplus 
} 
#endif 
+0

UnsatisfiedLinkError通常意味着用於構建的文件的體系結構與運行不同。你的JDK是64位還是32位?你建立'SO'文件的平臺是32還是64? – Pat

+0

@Pat都是64BIT –

+0

_ [使用SWIG與採用std :: string作爲參數的方法](http://support.microsoft.com/kb/9122511/using-swig-with-methods-that-take -stdstring作爲一種參數)_; TL; NR:你的** .i **文件需要'%include「std_string.i」' –

回答

1

事實證明,我對SWIG正在做的事情存在誤解。也許,你也是。

SWIG的目的是爲C/C++庫自動化構建包裝。它不是javah的替代產品。通過SWIG工作,您可以從C或C++代碼開始,並接收自動生成的C++和Java代碼。有了這個,你可以在你的項目中使用這些包裝Java類(在你的情況下,demoJNI)。您不要在您的Java代碼中聲明原生方法。通過包裝器Java類和包裝器C/C++代碼(Demo_wrap.cxxdemoJNI.java)與您的C++庫進行通信。

SWIG文檔明確指出,它不是將Java代碼連接到幾個本機函數的正確工具。它的設計目標是自動化使用Java,Python和許多其他高級語言來封裝大型C++項目的複雜API。

+0

非常感謝 –

0

在你的C++代碼,你應該這樣做:

extern "C" { 
    JNIEXPORT void JNICALL 

    Java_App_printHello(JNIEnv* env, jobject obj, jstring name) { 
     const char* c_name = env -> GetStringUTFChars(name , NULL); 
     std::cout << "Hello: "<< c_str << "\n"; 
     env->ReleaseStringUTFChars(name, c_name); 
    } 
} 
+1

這就是SWIG應該處理的事情。 –