Programmieren - alles kontrollieren 4.941 Themen, 20.715 Beiträge

Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!

DeepThinking / 17 Antworten / Baumansicht Nickles

Hallo, ich möchte auf eine in C geschriebene DLL mittles Java zugreifen. Also die DLL ist -wie gesagt - schon vorhanden; ich will lediglich sie in meinem Java-Programm einbinden, damit ich bestimmte Funktionen aufrufen kann. Ich habe Java Native Interface angeschaut und kann eigene DLL erstellen, die ich dann in Java-Programmen einbinden kann(mit System.loadLibrary). Aber was ist, wenn die DLL schon existiert!?


Konkret: ich habe FRME_GRABBER.DLL (in C geschrieben) und will sie im JAVA-Programm benutzen. z.B. möchte die Funktion long Grab(long fgh, FRAME *frh), was schon in dieser FRAME_GRABBER.DLL implementiert ist, in meinem JAVA-Programm benutzen.

bei Antwort benachrichtigen
vergisses DeepThinking „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Du kannst im Prinzip andere DLL´s über Wrapper Funktionen in JNI indirekt aufrufen. Beispiel:
/* Java Source */
public class MyTools
{
static
{
System.loadLibrary("MyTools");
}
public native static long JGrab(long fgh, JFrame fr);
}
/* C Source */
JNIEXPORT jlong JNICALL Java_MyTools_JGrab(JNIEnv *env,jlong fgh,jclass clsFR,jobject oFr)
{
return(Grab(fgh,clsFr,oFr);
}

Evtl. mußt Du in der JNI Funktion noch ein
LoadLibrary("FRME_GRABBER") ausführen.

Mir ist allerdings nicht ganz klar, wie Du ein Java Frame, ganz gleich ob aus AWT oder Swing, unter C grabben willst.
Das Java Frame ist ein Java Objekt, dessen Beschreibung als jclass Typ übergeben wird.
Letztendlich wird das Frame über die JVM zwar als Windows Frame
realisiert, aber da müßtest Du Dich wohl durch einen ganzen
Dschungel an Implementierungsdetails kämpfen.

Es wäre warscheinlich besser, wenn Du das Frame unter Java grabben
würdest.

bei Antwort benachrichtigen
mr.escape vergisses „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Ich glaube, es handelt sich hier um einen frame-grabber, um bilder von externen quellen einzulesen (vereinfacht dargestellt eine video karte) und nicht um java frames (die dll ist ja in C geschrieben). Lustiger wird es mit der C-definition von "FRAME *frh". Die muss in java dann genau nachgebildet werden.

mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
vergisses mr.escape „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Hi Mr. Escape,

in diesem Fall wird es erst so richtig interessant ;-)

Hi DeepThinking,

schau Dir mal die Klassen MediaTracker usw. an, vielleicht findest
Du da was Passendes.

Gruss

bei Antwort benachrichtigen
DeepThinking vergisses „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Ja genau, Mr. Escape,
ich habe eine Framegrabber-Karte, an der eine Kamera angeschlossen ist. Der Treiber ist in C geschrieben. Ich muss meine Anwendung in Java schreiben, die Bilder aus der Kamera erst mal liest/anzeigt und sie dann auswertet. Das Problem ist nun wie ich auf die Funktionen bzw. auf die dll mittels Java zugreifen kann.
Laut Java-Spezifikation von Sun muss es gehen, aber wie??
Man kann eventuell seine eigene DLL erstellen und im Java-Programm über JNI einbinden. Aber die DLL ist ja vorhanden..

bei Antwort benachrichtigen
mr.escape DeepThinking „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Ich bin wegen dem framegrabber aufmerksam geworden, habe aber noch nie was mit jni gemacht und in java nur sehr wenig. Ein kurzes googlen brachte mich auf diese seite. Allem anschein nach erfordern native libraries (hier dll) einen bestimmten aufbau (siehe vergisses). Es ist aber kein problem ein wrapper-dll für die externe dll zu bauen.
Wie die parameter übergeben werden müssen weiss ich aber nicht.

mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
vergisses mr.escape „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Hallo und guten Morgen zusammen.

Hallo DeepThinking,

für Aufrufe von C Routinen aus Java heraus müssen gewisse Calling Conventions eingehalten werden, eben JNI.
Die Funktionen in der Treiber DLL erfüllen diese Konventionen naturgemäß nicht. (ich habe sowas jedenfalls noch nie bei einer Treiber DLL gesehen).
Wenn Du diese Funktionen aufrufen willst, bleibt Dir also nichts anderes übrig, als in der bereits beschriebenen Weise eigene Funktionen nach JNI Konvention zu schreiben,
die ihrerseits die Funktionen in der Treiber DLL aufrufen bzw. deren
Ergebnisse zurück geben, eben "wrappen".
Dabei mußt Du aber warscheinlich ständig komplexe C Strukturen in Java Objekte hin und her wandeln, was sehr aufwendig und Performancelastig sein dürfte.
Liegen dann keine Standard Konstrukte wie z. B. AVI Formate vor,
kannst dann kaum was mit den übertragenen Daten anfangen.

Normalerweise bindet der Treiber doch ein Gerät in die (vermutlich Windows) Umgebung ein.
Die Philosophie dabei ist, die Geräteeigenschaften im Treiber zu lassen und die Daten der Geräte als Stream zu lesen bzw. schreiben.
Der Vorteil ist, daß sich die Applikationsentwickler nur noch wenig
mit den besonderen Eigenschaften eines Geräts beschäftigen müssen,
sondern einfach nur mit Datenströmen arbeiten.

Java unterstützt Stream Verarbeitung auf breiter Front, man spricht sogar schon von einem Stream Zoo ;-)

Ich würde mich erst mal in diese Richtung orientieren, denn LowLevel
Geräte Programmierung auf Treiberebene hat genauso seine Tücken (z. B Timingprobleme) wie JNI (z. B. Speicherverletzungen).

bei Antwort benachrichtigen
mr.escape vergisses „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Solche teile wie ein framegrabber haben selten os-treiber (wie z.b. twain) sondern in der regel eine api (häufig als ??-sourcecode, statische lib oder dll). Hier wird wohl nur die wrapper dll variante übrig bleiben, was die entwicklung einer dll in C erforderlich macht. Das mindeste dafür ist die kenntnis der struktur FRAME ("FRAME *frh") und eine eins zu eins (grössen und alignements) java umsetzung. Dafür und für das dynamische linken (runtime) ist noch eine header-datei erforderlich (lässt sich aber selber machen, teile (alles?) sind ja schon vorhanden) und bei der statische variante (loadtime) zusätzlich eine import-lib (das könnten tools machen, müsste man aber suchen).

mr.escape

"The man who trades freedom for security does not deserve nor will he ever receive either." - Benjamin Franklin"Wer seine Freiheit aufgibt, um Sicherheit zu erreichen, wird beides verlieren." - Georg Christoph Lichtenberg
bei Antwort benachrichtigen
DeepThinking Nachtrag zu: „Auf existierende DLL (in C geschrieben) mittels JAVA zugreifen!“
Optionen

Ich danke Euch! Ich versuche es mit Wraper Funktionen und hoffe darauf, dass es geht..
Danke erst mal:-)

Doch eine Frage noch, Wie sieht die Parameterübergabe auf der Java-Seite aus, wenn man in der ursprüngliche Funktoin mit "Pointer" zu tun hat?

bei Antwort benachrichtigen
vergisses DeepThinking „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hi,

erst mal zu den Calling Conventions innerhalb von Java.
Grundsätzlich kennt Java nur ein Call by Value.
Wenn Du aber einen Parameter übergibts, der nicht von einem
Basis Datentyp wie z. B. Integer, sondern ein Java Objekt ist,
so wird die Objectvariable zwar by Value übergeben,
ist aber eigentlich ein Handle auf das Original.
Damit hast Du eine ähnliche Verarbeitung wie by Pointern (call by Reference).
siehe auch
http://mindprod.com/jglosscallbyreference.html

Bei Aufrufen von nativen Methoden über JNI sieht es etwas anders aus.
Beispiel:
Java Methodendefinition:
public native static int tuwas(JFrame MyFrame);

Du kompilierst das Java Programm, bekommst ein *.class File
und erzeugst dann das C Header File mit "javah -jni

bei Antwort benachrichtigen
DeepThinking vergisses „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Danke Dir vergisses!
Nur das Problem ich komme aus der C seite und versuche die Funktionen in java zu nutzen!
Nun ganz konkret: Ich habe die Funktion
short OpenLibrary(LPSTR dllname, __PC_FRAME *interface, short sizeof(interface))
und sie ist in FRAME_GRABBER.DLL implementiert.
Der Tipp war, dass man mit Wrapper Funktionen arbeitet. D.h. ich definiere im Java-Code "Tools.java" die native Funktion
native short jOpenLibrary(string dllName, ??, ??)

Kompiliere javac Tools.java
dann javah -jni Tools
bekomme Tools.h
mit der Native Funktion
JNIEXPORT jshort JNICALL Java_Tools_jOpenLibrary(JNIEnv *, jobject, jstring, ??, ??);

Und in C code "ToolsImpl.c" rufe die ursprügliche Funktion auf!!

JNIEXPORT jshort JNICALL
Java_Tools_jOpenLibrary(JNIEnv *env, jobject obj, jstring dllname, ??, ??){
return(OpenLibrary("FRAME_GRABBER.DLL", &interface, sizeof(interface));
}

daraus mache ich meine MY_FRAME_GRABBER.DLL..

//Die Frage ist,wie soll die native methode in meinem java-Code aussiehen??
//Die Parameterübergabe in der Native Funktion
native short jOpenLibrary(string dllName, ??, ??)

Entschuldige für die vielen Fragen!
Aber das bereitet mir wirklich Kopfschmerzen, besonderes wenn man unter Zeitdruck steht.

Gruss DeepThinking..

bei Antwort benachrichtigen
vergisses DeepThinking „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hallo DeepThinking,

ich stamme auch aus der C/C++ Fraktion und mache Java erst seit
ca. 3,5 Jahren.

Ich werde Dir gerne helfen, habe aber leider erst heute Nachmittag
Zeit dafür, musst Dich etwas gedulden.

Gruss, vergisses

bei Antwort benachrichtigen
vergisses DeepThinking „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hallo,

wie ist "__PC_FRAME interface" denn definiert ?
Handelt es sich hier um eine Struktur oder ist es ein Zeiger
auf eine Funktion ?

Gruss, vergisses

bei Antwort benachrichtigen
DeepThinking vergisses „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hi vergisses,
Also in der Dokumentation zum Treiber ist die Funktion wie folgt definiert: short OpenLibrary(LPSTR dllnmae, __PX_FAR *interfac, short sizeof(interface));
Ich habe die header files IFRAME.h und PXC200.h
(Die Framegrabberkarte heißt PXC200 daher der name PXC200.h!!)angeschaut und da steht die Funktion wie folgt
short OpenLibrary(char __PX_FAR *file, void __PX_FAR *iface,short count); definiert.

1. Parameter ist dll-Name also FRAME_GARBBER.DLL
2. Parameter ist void
define makro #define __PX_FAR für den Präprozessor..

Bei wrapped-Funktion brauche ich doch nicht die Parameterübergabe ich brauche lediglich den Rückgabewert!! Oder??
Also mein Funktionsaufruf würde in auf java-Seite in "Tools.java" folgendermaßen definiert: native short jOpenLibrary();

und in ToolsImlp.c wird so ausschauen:

JNIEXPORT jshort JNICALL
Java_Tools_jOpenLibrary(JNIEnv *env, jobject obj){
return (OpenLibrary(FRAME_GRABBER.DLL, &pxc, sizefo(pxc));
}
Stimmts??

Die Frage ist, was wenn die Funktion so aussieht:
FRAME __PX_FAR *AllocateBuffer(short dy, short dy, short type);

wobei FRAME eine Struktur ist und kein primitiver Datentyp und ein Zeiger auf die Funktion??

typedef struct tagFRAME{
struct tagFRAME __PX_FAR *next;
short dx,dy;
short type;
unsigned char user_type;
unsigned char dma_type;
BUFFERDATA user;
BUFFERDATA dma;
void (__PX_CALL *close)(struct tagFRAME __PX_FAR *);
}FRAME;


Gruss DeepThinking

bei Antwort benachrichtigen
vergisses DeepThinking „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hi DeepThinking,
hier ein Beispiel, wobei ich für __PC_FRAME eine einfache Struktur
genommen habe.
Erst mal die Strukturdefinition und der Funktionsprototyp:
--------Datei frames.h--------------
#include

bei Antwort benachrichtigen
DeepThinking vergisses „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hi vergisses,
ich danke dir viel mals für deine Hilfe..
Der Weg ist mir nun klar. Ich dachte, das wäre einfacher mit JNI, aber man wird immer wiede überrascht:-)
Also nun an die Arbeit..

Gruss DeepThinking

bei Antwort benachrichtigen
vergisses DeepThinking „Danke viel mals!“
Optionen

Hi DeepThinking,

keine Ursache, kannst ja mal bei Gelegenheit berichten,
wie es geklappt hat.

Gruss, vergisses

bei Antwort benachrichtigen
vergisses DeepThinking „Danke! Ich versuche es über Wrapper Funktionen..“
Optionen

Hi DeepThinking,

ich bin übrigens nach wie vor der Meinung, daß es besser und einfacher
wäre, die Funktionalitäten komplett in C zu schreiben.

Ich würde einen C Prozess schreiben, der die Daten dem Java als
Stream zur Verfügung stellt.
Zusätzlich würde ich mit JNI eine kleine DLL schreiben,
die aus Java aufrufbare Funktionen zur Steuerung des C Prozesses
bereitstellt.
Diese DLL könnte mit dem C Prozess über IPC
(z. B. Messages, bitte nicht mit Windows Messages verwechseln oder
named Pipes) oder Netzwerk Sockets kommunizieren.

Gruss, vergisses

bei Antwort benachrichtigen