Il n'y a pas de trace d'erreur, le new TTable() fait crasher l'application lorsqu'il est applelé dans une DLL non chargée par un exécutable Borland.

J'ai besoin de créer une base de données paradox et d'écrire des lignes dans cette BDD.
Ce code a été fait dans une DLL sous Borland C++ 5.0 et fonctionne lorsqu'il est lancé par un EXE créé et compilé sous Borland C++ Builder 5.
Il est possible d'appeler les fonctions de la DLL par JNI à partir de Java et cela fonctionne (les appels JNI).
Ce qui ne fonctionne pas c'est la création d'instance de TTable (new TTable) qui plante lorsque la DLL est chargée via :
  • JNI
  • Un exécutable compilé sous MinGW.

Lorsqu'un exécutable fait le même travail (même code) mais compilé
sous Borland C++ Builder 5 celà fonctionne.

Le code créé un objet JNIEnv et JNINativeInterface_ et initialise les callbacks afin de
"simuler" les appels par JNI Le code contenu dans la DLL créé un singleton
d'une classe. L'appel de la création de la BDD fait simplement :

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
try
{
    //-----------------------------
    // Creating database structure
    m_pTable = new TTable(NULL);// <------------ CRASH ICI
    return 0;
}
catch (Exception &_rException)
{ // Close opened database when error occurs // Record exception error 
    m_strLastError = _rException.Message;
    CloseDatabase();
}
catch (...)
{ // Close opened database when error occurs 
  // Record unknonw error 
    m_strLastError = "Unknown error"; 
    CloseDatabase();
}
Le code de l'exécutable est le suivant :

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
#include <iostream>
#include <windows.h>
#include <jni.h>
#include <string>
 
using namespace std;
 
typedef jstring (*GetLastDBError)(JNIEnv *, jobject); typedef jint (*CreateDatabase)(JNIEnv *, 
jobject, jstring);
 
#ifdef __cplusplus
extern "C" {
#endif
 
const char * JNICALL GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy)
{
    return (const char *) str;
}
 
void JNICALL ReleaseStringUTFChars(JNIEnv *env, jstring str, const char* chars)
{
}
 
jstring JNICALL NewStringUTF(JNIEnv *_pEnv,const char *_pszString)
{
    return jstring(_pszString); 
}
 
#ifdef __cplusplus
}
#endif
 
int main()
{
    HINSTANCE hDLL = ::LoadLibrary("ParadoxWriter.dll");
 
    if (hDLL != NULL)
    {
        JNIEnv jniEnvironnement;
        JNINativeInterface_ nativeInterface;
 
        // Création
        memset(&nativeInterface,0,sizeof(JNINativeInterface_));
        memset(&jniEnvironnement,0,sizeof(JNIEnv));
        jniEnvironnement.functions = &nativeInterface;
 
        jobject objObject;
 
        nativeInterface.GetStringUTFChars       = GetStringUTFChars;
        nativeInterface.ReleaseStringUTFChars   = ReleaseStringUTFChars;
        nativeInterface.NewStringUTF            = NewStringUTF;
 
        CreateDatabase lpfProcFctCreateDatabase = (CreateDatabase) 
        ::GetProcAddress(hDLL,"Java_parser_DB_DBExporter_CreateDatabase");
        GetLastDBError lpfProcFctGetLastDBError = (GetLastDBError) 
        ::GetProcAddress(hDLL,"Java_parser_DB_DBExporter_GetLastDBError");
 
        if (lpfProcFctCreateDatabase!=NULL && lpfProcFctGetLastDBError!=NULL)
        {
            jstring strLastError = (*lpfProcFctGetLastDBError)(&jniEnvironnement,objObject); // MARCHE !!
            jint iRet = (*lpfProcFctCreateDatabase)(&jniEnvironnement,objObject,jstring("D:\\Ma_user\\Converters\\Format_DB\\Validation\\TEST_64\\Output\\toto.db")); // --> CRASH
        }
    }
 
    return 0;
}
Erreur provoquée sous MinGW :
In RaiseException () (C:\WINDOWS\system32\kernel32.dll)
Le même code exécuté sur un exe complié avec Borland C++ Builder 5 fonctionne parfaitement.
J'ai utilisé DbiInit(NULL); mais ça ne change rien.
La variable Session est bien initialisée, on peut même avoir accès à ses attributs mais pas tous, l'appel de Session->GetConfigMode() créé le crash. Peut être que lorsqu'un TTable est créée, elle appelle cette méthode ????
Mais alors pourquoi dans le cas d'un appel par un exe borland cela fonctionne ?