2012-11-10 2 views
4

J'ai un propre plugin Eclipse de construction où j'ai besoin d'appeler une DLL C++.Plugin Eclipse, appel C++ dll

J'ai essayé de le faire en deux étapes: 1. en dehors de mon Eclipse plugin via Java MainProgram appelant le C++ dll 2. Essayez d'obtenir dans mon plugin (ce qui est là le problème)

  1. en dehors du plugin Eclipse.

Code Java principal HelloWorld.java.

class HelloWorld { 
    //public native void print(); //native method 
    public native String print(String msg); //native method 

    static //static initializer code 
    { 
     System.loadLibrary("CLibHelloWorld"); 
    } 

    public static void main(String[] args) 
    { 
    //HelloWorld hw = new HelloWorld(); 
     //hw.print(); 

    String result = new HelloWorld().print("Hello from Java"); 

    System.out.println("In Java, the returned string is: " + result); 
    } 
} 

Compilé via la commande: "C: \ Program Files \ Java \ jdk1.6.0_34 \ bin \ javac" HelloWorld.java

Puis je fis un HelloWorld.h h fichier pour le C++ dll via:

"C: \ Program Files \ Java \ jdk1.6.0_34 \ bin \ javah" HelloWorld

Le h fichier ressemble à ceci:

#include <jni.h> 
/* Header for class HelloWorld */ 

#ifndef _Included_HelloWorld 
#define _Included_HelloWorld 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  HelloWorld 
* Method: print 
* Signature: (Ljava/lang/String;)Ljava/lang/String; 
*/ 
JNIEXPORT jstring JNICALL Java_HelloWorld_print 
    (JNIEnv *, jobject, jstring); 

#ifdef __cplusplus 
} 
#endif 
#endif 

Maintenant, le C++ de CLibHelloWorld.cpp dll:

#include "HelloWorld.h" 
#include "jni.h" 
#include "stdafx.h" 
#include "tchar.h" 

#import "..\ManagedVBDLL\bin\Debug\ManagedVBDLL.tlb" raw_interfaces_only 
using namespace ManagedVBDLL; 

JNIEXPORT jstring JNICALL Java_HelloWorld_print(JNIEnv *env, jobject thisObj, jstring inJNIStr) { 
    jboolean blnIsCopy; 
    const char *inCStr; 
    char outCStr [128] = "string from C++"; 

    inCStr = env->GetStringUTFChars(inJNIStr, &blnIsCopy); 
    if (NULL == inCStr) return NULL; 

    printf("In C, the received string is: %s\n", inCStr); 
    env->ReleaseStringUTFChars(inJNIStr, inCStr); 

    return env->NewStringUTF(outCStr); 
} 

Construire la dll

Quand je lance le programme principal java ... tout fonctionne très bien!

  1. essayer de le faire dans mon plugin Eclipse (ce qui est là le problème)

je fait une classe qui devrait appeler le dll C++:

package org.eclipse.ui.examples.recipeeditor.support; 
import org.eclipse.jface.dialogs.MessageDialog; 

public class HelloWorld { 
    public native String print(String msg); //native method 

    static //static initializer code 
    { 
     try { 
      System.loadLibrary("CLibHelloWorld"); //$NON-NLS-1$ 
     } catch (Exception e) { 
      e.printStackTrace(); 
      MessageDialog.openInformation(null, "HelloWorld", "HelloWorld Catch: " + e.getMessage()); 
     } 
    } 
} 

et l'appeler comme cela:

HelloWorld hw = new HelloWorld(); 
result = hw.print("Hi from Eclipse"); 

Ensuite, je reçois cette erreur sur hw.print (la charge de la DLL est terminée):

java.lang.UnsatisfiedLinkError: org.eclipse.ui.examples.recipeeditor.support.HelloWorld.print (Ljava/lang/String;) Ljava/lang/String;

Une longue histoire, mais comment puis-je le résoudre?

Merci.

+3

Vous devez placer la DLL à la bonne place et indiquer à Eclipse où elle se trouve. http://stackoverflow.com/questions/661320/how-to-add-native-library-to-java-library-path-with-eclipse-launch-instead-of – Aubin

+0

Oui. Au début, l'instruction loadlibrary a échoué, mais j'ai corrigé cela en ajoutant un chemin de bibliothèque à Eclipse. Après que la déclaration de loadlibrary est allée oke. – kahoona

Répondre

0

System.loadLibrary ne charge la bibliothèque que si elle est disponible dans LD_LIBRARY_PATH (Linux) ou dans PATH (Windows). Vous devez également respecter le nom correct. Pas sûr dans Windows, mais dans Linux si vous chargez CLibHelloWorld comme vous l'avez fait, votre DLL doit s'appeler libCLibHelloWorld.so. Je suppose qu'il existe un System.getNativeMethodName ou quelque chose comme ça pour que vous puissiez le découvrir. Quoi qu'il en soit, ce n'est pas ma façon privilégiée de charger les DLL, car vous dépendez de beaucoup de paramètres d'environnement. Au lieu de cela, vous pouvez utiliser System.load (dll_full_path) pour charger votre DLL. Cela a le même effet, mais vous avez plus de contrôle.

Si vous chargez votre DLL en sucessfully utilisant cette méthode, cependant, et ne cesse de se l'erreur ci-dessus lorsque vous essayez d'appeler votre méthode native, jetez un oeil sur les dépendances de DLL. Vous devez d'abord charger les dépendances, puis la lib que vous voulez appeler.

Par exemple, si vous voulez charger DLL1, qui dépend de DLL2, qui dépend de DLL3, vous devez faire:

System.load(dll3_path); 
System.load(dll2_path); 
System.load(dll1_path); 
0

Le nom de la méthode dans le code natif doit correspondre à la classe et empaqueter nom de la classe java. Puisque votre classe HelloWorld est passée du package par défaut à org.eclipse.ui.examples.recipeeditor.support, vous devrez changer le nom de la méthode.

Il suffit de réexécuter javah avec votre nouvelle classe pour obtenir le fichier d'en-tête correct.

BTW, il ne devrait pas être nécessaire de définir une bibliothèque chemin séparé si vous définissez correctement le dll dans votre OSGI-paquet en utilisant quelque chose comme

Bundle-NativeCode: mydll.dll ; osname=win32 ; processor=x86 

et inclure la dll dans le répertoire racine de votre plugin.