Bonjour,

J'ai un problème lors de l'interfaçage d'une dll existante avec mon code Java.
J'ai fait le tour des topics parlant du problème, mais je n'ai pas trouvé de solution... Le problème, c'est un UnsatisfiedLinkError sur une des méthodes de la dll...


Je décrit toutes les étapes :
- Logiciels : Eclipse pour la partie Java - Visual Studio 6 pour la partie C++ - le tout sous Windows

1) Ecriture du ".java" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
public class LibraryInterface {
	static {
		System.loadLibrary("LibraryInterface");
		System.out.println("dll loadée!");
	}
 
 
	protected ArrayList channelsList;
 
 
 
	public LibraryInterface() {
		channelsList = new ArrayList();
	}
 
 
	public boolean loadHeader(String pathname) {
		File file = new File(pathname);
 
		if (file.exists()) {
			openFile(pathname);
			return true;	
		}
		else {
			return false;	
		}
	}
 
	public boolean load(String pathname, int i) {
		// on ne fait rien pour l'instant...
		return false;
	}
 
 
	/** Méthodes de gestion des fichiers */
	public native boolean openFile(String pathname);
	public native boolean closeFile();
	public native int getChannelsNumber();
 
	[...]
2) génération du ".h" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class LibraryInterface */
 
#ifndef _Included_LibraryInterface
#define _Included_LibraryInterface
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     LibraryInterface
 * Method:    openFile
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_LibraryInterface_openFile
  (JNIEnv *, jobject, jstring);
 
/*
 * Class:     LibraryInterface
 * Method:    closeFile
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_LibraryInterface_closeFile__
  (JNIEnv *, jobject);
 
/*
 * Class:     LibraryInterface
 * Method:    getChannelsNumber
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_LibraryInterface_getChannelsNumber
  (JNIEnv *, jobject);
 
 
[...]
 
 
#ifdef __cplusplus
}
#endif
#endif
3) Codage du ".cpp" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
 
// LibraryInterface.cpp : Defines the entry point for the DLL application.
//
 
#include "stdafx.h"
#include "LibraryInterface.h"
#include <string.h>
 
//Déclaration des variables membre :
RDTiffDataFile::IRDTiffDataFilePtr pRDTiffDataFile;
 
 
 
/*********************************************************************
 * Méthodes d'accés aux données : Channels, Beams, Gates, DataGroups *
 *********************************************************************/
 
/*
 * Méthode retournant un pointeur vers la liste de Channels.
 */
RDTiffDefinition::IChannelsPtr getChannels() {
	// Accés à la liste des Channels
	RDTiffDefinition::IChannelsPtr pChannels;
	pChannels = pRDTiffDataFile->Channels;
 
	return pChannels;
}
 
/*
 * Méthode retournant le Channel numéro channelId.
 */
RDTiffDefinition::IChannelPtr getChannel(int channelId) {
	/*
	// Accés à la liste des Channels
	RDTiffDefinition::IChannelsPtr pChannels;
	pChannels = pRDTiffDataFile->Channels;
	*/
	RDTiffDefinition::IChannelsPtr pChannels = getChannels();
 
	// Accés au Channel numéro channelId
	RDTiffDefinition::IChannelPtr pChannel;
	pChannel = pChannels->Item[channelId];
 
	return pChannel;
}
 
/*
 * Méthode retournant le Beam numéro beamId du Channel numéro channelId.
 */
RDTiffDefinition::IBeamPtr getBeam(int channelId, int beamId) {
	RDTiffDefinition::IChannelPtr pChannel = getChannel(channelId);
	RDTiffDefinition::IBeamsPtr pBeams = pChannel->Beams;
	RDTiffDefinition::IBeamPtr pBeam = pBeams->Item[beamId];
 
	return pBeam;
}
 
/*
 * Méthode retournant la Gate numéro gateId du Beam numéro beamId du Channel numéro channelId.
 */
RDTiffDefinition::IGatePtr getGate(int channelId, int beamId, int gateId) {
	RDTiffDefinition::IBeamPtr pBeam = getBeam(channelId, beamId);
	RDTiffDefinition::IGatesPtr pGates = pBeam->Gates;
	RDTiffDefinition::IGatePtr pGate = pGates->Item[gateId];
 
	return pGate;
}
 
/*
 * Méthode retournant le DataGroup numéro groupId de la Gate numéro gateId 
 * du Beam numéro beamId du Channel numéro channelId.
 */
RDTiffDefinition::IDataGroupPtr getDataGroup(int channelId, int beamId, int gateId, int groupId) {
	RDTiffDefinition::IGatePtr pGate = getGate(channelId, beamId, gateId);
	RDTiffDefinition::IDataGroupsPtr pGroups = pGate->DataGroups;
	RDTiffDefinition::IDataGroupPtr pGroup = pGroups->Item[groupId];
 
	return pGroup;
}
 
/*********************************************************************/
 
 
 
 
 
 
 
 
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
 
/*
 * Class:     LibraryInterface
 * Method:    openFile
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_LibraryInterface_openFile
  (JNIEnv * env, jobject, jstring path)
{
	RDTiffDataAccess::IRDTiffDataPtr pRDTiffData;
 
	HRESULT hr = pRDTiffData.CreateInstance(_uuidof(RDTiffDataAccess::RDTiffData));
 
	if (FAILED(hr)) {
		// Traitement de l'exception
		printf("Erreur lors de l'ouverture du fichier : pRDTiffData.CreateInstance()");
		throw hr;
		return FALSE;
	}
 
	// This following is to get a smart pointer on a file control object.
	pRDTiffDataFile = pRDTiffData->RDTiffDataFile;
	hr = pRDTiffDataFile->OpenFile(env->GetStringUTFChars(path,0));
 
	if (FAILED(hr)) {
		// Traitement de l'exception
		printf("Erreur lors de l'ouverture du fichier : pRDTiffDataFile->OpenFile()");
		throw hr;
		return FALSE;
	}
 
	/********************************************
        // The following is to read the channels.
        RDTiffDefinition::IChannelsPtr pChannels;
        pChannels = pRDTiffDataFile->Channels;
 
        // The following is to read the first channel
        RDTiffDefinition::IChannelPtr pChannel;
        pChannel = pChannels->Item[1];
        *********************************************/
 
    return TRUE;
}
 
/*
 * Class:     LibraryInterface
 * Method:    closeFile
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_LibraryInterface_closeFile__
  (JNIEnv * env, jobject)
{
 
	HRESULT hr = pRDTiffDataFile->CloseFile();
 
	if (FAILED(hr)) {
		// Traitement de l'exception
		printf("Erreur lors de la fermeture du fichier");
		throw hr;
		return FALSE;
	}
 
    return TRUE;
}
 
/*
 * Class:     LibraryInterface
 * Method:    getChannelsNumber
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_LibraryInterface_getChannelsNumber
  (JNIEnv * env, jobject)
{
	printf("On va faire du getChannelNumbers()");
	// Accés à la liste des Channels
	RDTiffDefinition::IChannelsPtr pChannels = getChannels();
	printf("On a fait du getChannels()");
 
	// On retourne le nombre de Channels
	printf("On retourne %d", pChannels->Count);
	return pChannels->Count;
}
 
[...]
 
}
4) Génération de la dll en mode "release" via Visual Studio.

5) Déplacement de la dll dans le répertoire racine de mon projet Java (lors de la génération, elle était dans le dossier "MyProjects" du répertoire d'install de Visual Studio)

6) Appel de la classe chargeant la dll :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
	public Reader(File file) {
		this.setPathname(file.getPath());
		this.setFilename(file.getName());
		this.setExtension(FileUtilities.getExtension(file));
 
		libraryUse = new LibraryInterface();
		libraryUse.loadHeader(pathname);
		cscanNb = libraryUse.getChannelsNumber();
 
[...]
Dans la console, j'obtiens ça :
dll loadée!
java.lang.UnsatisfiedLinkError: openFile
La dll est chargée, mais la fonction n'est pas trouvée, alors que la déclaration correspond bien (enfin, si j'ai pas des yeux de taupe...)

Quelqu'un saurait pourquoi ça ne marche pas?
Merci d'avance!