2013-08-20 5 views
0

J'essaie de créer une interface graphique qui va essayer d'interfacer des périphériques CAN connectés à l'ordinateur et permettre la communication entre l'ordinateur et un microcontrôleur. La plupart du travail est fait en Java, mais le code CAN est écrit en C++, et appelé depuis Java en utilisant JNI. Je travaille avec Visual Studio 2013 pour le C++ et Eclipse pour le Java. Le programme fonctionne correctement sur l'ordinateur de développement, mais je n'ai aucune expérience en création de DLL et je ne peux pas exécuter le programme sur un autre ordinateur. J'ai utilisé Dependency Walker pour avoir une idée de la DLL que je devrais associer à l'application, et à ce stade, j'ai inclus toutes les DLL qui ont manqué (il y en a quelques-unes qui manquent encore, mais ça dit ceux-ci manquent également sur l'ordinateur de développement, et je crois que c'est juste un problème avec Dependency Walker).Comment créer une DLL redistribuable qui fonctionnera sur d'autres ordinateurs

Le dossier de l'application contient un fichier JAR exécutable de l'interface graphique, de la DLL que j'ai créée et des DLL dépendantes. J'essaie d'exécuter l'application à partir de la ligne de commande avec "java -jar {application.jar}". Je reçois l'erreur suivante:

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: C:\Users\David\Dropbox\ATPBoardInterface\CANMessager7.dll: A dynamic link library (DLL) initialization routine failed 
    at java.lang.ClassLoader$NativeLibrary.load(Native Method) 
    at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1939) 
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1864) 
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1854) 
    at java.lang.Runtime.loadLibrary0(Runtime.java:845) 
    at java.lang.System.loadLibrary(System.java:1084) 
    at model.CANController.<clinit>(CANController.java:34) 
    at main.Main$1.run(Main.java:70) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721) 
    at java.awt.EventQueue.access$200(EventQueue.java:103) 
    at java.awt.EventQueue$3.run(EventQueue.java:682) 
    at java.awt.EventQueue$3.run(EventQueue.java:680) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:691) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:97) 

Je suis à la recherche de suggestions sur la façon de résoudre ce problème. Quelque chose que je peux partager avec n'importe quel autre ordinateur Windows qui sera facile à installer et à exécuter pour l'utilisateur final. Edit: En cas de différence, le programme repose sur l'utilisation du logiciel CAN de National Instruments. J'ai inclus un certain nombre de DLL dans le dossier de l'application liées à ce que Dependency Walker énumérés, mais je ne suis pas sûr si cela suffit. Peut-être que l'ordinateur cible aura besoin que certains logiciels de National Instruments soient déjà installés pour fonctionner, et s'il manque, cela pourrait causer l'échec de l'initialisation de la DLL? Je ne suis pas assez familier dans ce genre de région pour être sûr de toute façon.

Edit 2: Voici ce que j'ai emmitouflé dans mon dossier de l'application:

20/08/2013 10:56 <DIR>   . 
20/08/2013 10:56 <DIR>   .. 
20/08/2013 08:26   427,170 ATPBoardInterface.jar 
20/08/2013 09:28   182,928 CANMessager.lib 
20/08/2013 08:52   201,728 CANMessager7.dll 
15/08/2013 16:28   30,720 CANMessagerXP.dll 
16/06/2013 21:11   966,224 msvcr120.dll 
11/07/2006 18:35   348,160 msvcr71.dll 
13/10/2012 11:00   655,872 msvcr90.dll 
01/06/2011 17:59   45,192 Nican.dll 
06/04/2010 17:44   72,224 NicanCfq.dll 
06/04/2010 17:44   125,472 nicanDBA.dll 
01/06/2011 17:59   197,784 NIcanFrm.dll 
01/06/2011 17:59   18,080 NIcanpu.dll 
01/06/2011 17:59   61,568 NicanTsk.dll 
26/01/2012 15:54   19,632 nipal32.dll 
26/01/2012 16:11   309,920 nipalu.dll 
26/01/2012 15:53   12,968 nipalut.dll 
19/08/2013 16:18    772 README.txt 
20/08/2013 08:34 <DIR>   res 
20/08/2013 10:56     0 temp.txt 
20/08/2013 09:43   6,494,784 vcredist_x86.exe 
       19 File(s)  10,171,198 bytes 
       3 Dir(s) 416,406,867,968 bytes free 

Je ne suis pas sûr de ceux-ci sont nécessaires.

+0

avez-vous essayé d'écrire un petit programme C++ natif qui charge la bibliothèque? –

+0

La plupart des gens utilisent un outil appelé * installateur * pour gérer les dépendances. Je vous recommande de faire la même chose. Notez également que le regroupement du programme d'installation redistribuable de MSVC ne fonctionne pas réellement, ces DLL doivent être * installées * sur la machine de l'utilisateur. Un installateur peut le faire pour vous. –

+0

@Tobias Langner, je ne l'ai pas, mais serait-il bénéfique d'essayer?Je sais que le code lui-même fonctionne car il s'exécute correctement lorsque je l'appelle depuis Java (avec JNI) sur la machine de développement. – Tagc

Répondre

0

Un problème pourrait être un problème de 32 bits/64 bits. Si votre DLL d'interface CAN est une DLL 32 bits et que vous exécutez Java 64 bits, cela ne fonctionnera pas. L'exécution de DLL 64 bits avec Java 32 bits ne fonctionnera pas non plus.

La seule solution consisterait à compiler la DLL en tant que version 32 et 64 bits et fournir les deux versions de DLL.

Si les problèmes ne sont pas résolus par les bits 32/64, vous pouvez utiliser l'outil SysInternals ProcessExplorer pour voir toutes les tentatives d'accès aux fichiers. Dans ce cas, vous verrez si Java essaie d'accéder à un fichier DLL qui n'est pas présent.

Une solution pour le problème 32 bits/64 bits serait l'utilisation d'un fichier EXE de ligne de commande au lieu d'un fichier DLL. Les données sont transférées à l'aide de la sortie et de l'entrée standard (côté C++) et en utilisant InputStream et OutputStream de la classe java.lang.Process du côté Java. Cela fonctionnera toujours avec un fichier EXE 32 bits.

+0

Je n'utilise que Java 32 bits. Je vais essayer SysInternals ProcessExplorer, merci. – Tagc

+0

J'ai couru deux versions de mon interface graphique, une où elle essaye de charger ma DLL et une où elle ne le fait pas. J'ai utilisé Process Explorer pour produire une liste de DLL chargées dans chaque cas, les a enregistrées dans des fichiers et créé un script pour afficher uniquement les DLL qui apparaissent dans un cas mais pas dans l'autre. J'ai ajouté toutes les DLL de cette liste dans mon répertoire d'application qui n'étaient pas déjà là. Toujours pas de chance cependant. Il ne se plaint pas d'une DLL manquante pour être juste, il dit juste que "la routine d'initialisation DLL a échoué". Existe-t-il un moyen de savoir quelles DLL ont été chargées jusqu'à présent et lesquelles sont en train de charger? – Tagc

Questions connexes