PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : so-Datei unter Linux erstellen geht nicht



Lt.Henry
25-08-2006, 11:25
Hallo

Um mein Problem besser zu veranschaulichen hole ich etwas weiter aus.

Eine Java-Anwendung arbeitet Hand in Hand mit Cobol-DLLs. Da Java die Cobol-DLLs nicht direkt aufrufen kann, gibt es eine in C geschriebene Wrapper-DLL die das erledigt. Unter Windows alles kein Problem. Doch nun soll das komplette Projekt unter Linux laufen. Hier gibt es nun Probleme bei der Wrapper Datei. Ich kann keine SO-Datei erstellen. Der Fehler mit der windows.h ist mir klar. Aber warum hat er unter Linux Probleme mit dem anderen Code was unter Windows einwandfrei läuft?

Fehlermeldung:


StradaDialogTest.c:3:35: error: include/linux/windows.h: Datei oder Verzeichnis nicht gefunden
StradaDialogTest.c:7: Warnung: Parameternamen (ohne Typen) in Funktionsdeklaration
StradaDialogTest.c:10: Fehler: syntax error before »stradainst«
StradaDialogTest.c:10: Warnung: Initialisierung erzeugt Ganzzahl von Zeiger ohne Typkonvertierung
StradaDialogTest.c:10: Warnung: Datendefinition hat keinen Typ oder Speicherklasse
StradaDialogTest.c: In Funktion »Java_wam_StradaDialog_loadstrada«:
StradaDialogTest.c:20: Warnung: Vergleich zwischen Zeiger und Ganzzahl
StradaDialogTest.c:21: Fehler: »TRUE« nicht deklariert (erste Benutzung in dieser Funktion)
StradaDialogTest.c:21: Fehler: (Jeder nicht deklarierte Bezeichner wird nur einmal aufgeführt
StradaDialogTest.c:21: Fehler: für jede Funktion in der er auftritt.)
StradaDialogTest.c:30: Warnung: Zuweisung erzeugt Ganzzahl von Zeiger ohne Typkonvertierung
StradaDialogTest.c:31: Fehler: »FALSE« nicht deklariert (erste Benutzung in dieser Funktion)
StradaDialogTest.c: In Funktion »Java_wam_StradaDialog_cancelstrada«:
StradaDialogTest.c:42: Fehler: »FALSE« nicht deklariert (erste Benutzung in dieser Funktion)
StradaDialogTest.c:45: Warnung: Zuweisung erzeugt Ganzzahl von Zeiger ohne Typkonvertierung
StradaDialogTest.c:47: Fehler: »TRUE« nicht deklariert (erste Benutzung in dieser Funktion)
StradaDialogTest.c: In Funktion »Java_wam_StradaDialog_callstrada«:
StradaDialogTest.c:54: Fehler: »FALSE« nicht deklariert (erste Benutzung in dieser Funktion)
StradaDialogTest.c:64: Fehler: »TRUE« nicht deklariert (erste Benutzung in dieser Funktion)


Code:

StradaDialogTest.h


#include <jni.h>

JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_loadstrada (JNIEnv *, jobject);
JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_cancelstrada (JNIEnv *, jobject);
JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_callstrada (JNIEnv *, jobject, jbyteArray);


StradaDialogTest.c


//wrapper fuer native aufruf von libSPHSTRADA.so

#include <windows.h>
#include <string.h>
#include "StradaDialogTest.h"

typedef void (*STRADAPROC)(LPCTSTR);

//instanz der *.so und funktionsadressen
HINSTANCE stradainst=NULL;

STRADAPROC stradaproc=NULL;

//uebergabe arrays
jbyte *stradaeinaus;

//libSPHSTRADA.so laden und funktionsadresse holen
JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_loadstrada(JNIEnv *env,jobject obj)
{
if (stradainst != NULL) //damit beim evtl. mehrfachaufruf nicht mehrfach geladen wird
return TRUE;
stradainst=LoadLibrary("libSPHSTRADA.so");
if (stradainst)
{
stradaproc=(STRADAPROC)GetProcAddress(stradainst,"SPHSTRADA");
if (!stradaproc)
{
//*.so freigeben und zurck
FreeLibrary(stradainst);
stradainst=NULL;
return FALSE;
}
return TRUE;
}
return FALSE;
}

//libSPHSTRADA.so freigeben
JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_cancelstrada(JNIEnv *env,jobject obj)
{
if (!stradainst)
return FALSE;
if (!FreeLibrary(stradainst))
return FALSE;
stradainst=NULL;
stradaproc=NULL;
return TRUE;
}

//libSPHSTRADA.so aufrufen
JNIEXPORT jboolean JNICALL Java_wam_StradaDialog_callstrada(JNIEnv *env,jobject obj,jbyteArray arr)
{
if (!stradaproc)
return FALSE;
//array elemente zuweisen
stradaeinaus=(*env)->GetByteArrayElements(env,arr,0);
if (!stradaeinaus) //action nur wenn kein nullzeiger
return FALSE;
//action
(stradaproc)(stradaeinaus);
//freigeben
(*env)->ReleaseByteArrayElements(env,arr,stradaeinaus,0);
//alles ok zurck
return TRUE;
}


Ich kompilliere wie folgt:

gcc -fPIC -c StradaDialogTest.c
gcc -shared -o libStradaDialogTest.so StradaDialogTest.o

Es wäre schön, wenn Ihr mir helfen könnt. :)

Melanie

Yonibear
25-08-2006, 16:23
Ganz einfach, TRUE und FALSE sind windows-spezifische Makros um unter C booleans nachzubilden. Durch ein einfaches

#define TRUE 1
#define FALSE 0
kannst du das aber nachbilden. Weiterhin benutzt du die Windows-API für dlls, dazu gehören der Handle HINSTANCE und Funktionen wie LoadLibrary, GetProcAdress und FreeLibrary. Die Linux-Äquivalente sind dlopen, dlsym und dlclose, und als Handle einen void-Pointer, dazu brauchst du den Header dlfcn.h.
Alternativ kannst du auch den winegcc verwenden um Windows-Code zu kompilieren, dort steht dann die windows.h und die meisten Win-Funktionen zur Verfügung. Allerdings bin ich mir nicht sicher, ob die DLL-Funktionen von Wine geeignet sind um .so's zu öffnen, oder ob sie nur mit DLLs umgehen können.

anda_skoa
25-08-2006, 16:25
Das sieht nach einem Windows Quelltext aus, es sei denn windows.h ist eine spezielle Anpassung, die unter Linux entsprechende Kompatabiltätsdeklarationen beinhält.

Also zB das unter jedem POSIX kompatiblen Betriebsystem, also alles außer Windows :rolleyes:, der Befehl zum Laden einer shared Library dlopen heißt und der zum Auflösen eines Symbols darin dlsym

Leider vermute ich, daß hier versucht wird, eine windowspezifischen Code zu kompilieren, ohne vorher Anpassungen an Standard-APIs vorgenommen zu haben.

Ciao,
_

panzi
28-08-2006, 22:00
Noch ein Hinweis zu GetProcAddress Vs. dlsym:
Mit GetProcAddress holt man sich einen Pointer auf eine Funktion, mit dlsym holt man einen auf eine Variable. Unter x86 sind solche Pointer zufällig glaich. Also es ist wurscht. Aber es gibt systeme, bei denen ein casten eines Funktionspointer in ein void* und umgekehrt nicht geht. Als workaround kann man mit GetProcAddress eine funktion aus der DLL holen, die einen als rückgabewert die gewünschte Variable (bzw. Pointer) liefert und als workaround bei dlsym holt man eben z.B. ein Objekt, welches seiner seits einen Funktionspointer beinhaltet.

Also nur das zu dem Warning, das auftritt, wenn man die beiden Funktionen nicht korrekt einsetzt. Aber wie gesagt, unter x86 ists eh wurscht.