# liblvdave (libnodave und LabVIEW)



## ctb1 (14 März 2005)

Bin gerade dabei LabVIEW mit libnodave zu verbinden

Status:
1. libnodave mit VS.NET übersetzt.
2. liblvdave mit VS.NET erstellt (auf libnodave aufgesetzt).
3. LVdaveXXX VI,s erzeugt.
4. Auslesen von Bytes über MPI funktioniert bereits.

Wer hat Erfahrung mit libnodave unter Windows?

libnodave http://libnodave.sourceforge.net 
liblvdave url für download folgt.
LVdaveXXX url für download folgt.


----------



## Zottel (14 März 2005)

Interessant. Benutzt du die existierende Windows-.DLL? Bz.W sag mir eben, was VS ist? Visual Studio? Kompiliert also die C-Quellen?
Mir würde es darum gehen, daß es möglichst nur eine C-Quelle gibt. Auf diese Weise würden alle Anwendungen von Erweiterunge/Verbesserungen am Hauptzqweig automatich profitieren. Falls du Änderungen am C-Code machen mußtest, würde ich die gerne per condiional defines in den Code einpflegen.


----------



## Anonymous (14 März 2005)

Erstmal danke für deine Antwort

Als C Kompiler verwende ich Microsoft Visual C++ .NET 7.0
Für die Anbindung an LabVIEW die Datei 'labview.h' und labview.c' in das Projekt eingefügt.
Das Hauptproplem bei LabVIEW ist die übergabe von Parameter beim Aufruf von DLL Funktionen (Hab auch zu wenig Erfahrung damit).

Mir währe es auch recht, daß es möglichst nur eine C-Quelle gibt, deshalb würd ich dich bitten den LabVIEW Code in deinen Code einzupflegen.

Aktuelle Version: http://www.c-n-t.at/ctb/download/libnodave.rar


----------



## Zottel (14 März 2005)

Danke für den Code!

Zu den Änderungen:
nodave.c enthält keine. Das ist sehr gut 
log.h: Wenn es darum geht, die 
#define __filename
einheitlich zu gestalten, kein Problem.
nodave.h:
Das 
#define BCCWIN
#define DOEXPORT
gehört nicht in die Header Datei. Es ist ja gerade dafür da, daß dieselbe header-Datei unter verschiedenen Bedingungen verschieden behandelt wird.
Wenn du es unbedingt zum Bestandteil von Code machen möchtest, statt es als conditional defines irgendwo im Projekt file, Makefile oder im Copiler Options Dialog zu setzen, ist die richtige Art:

datei meincode.c:
#define BCCWIN
#define DOEXPORT
#include "nodave.h"

Die Kommentare hinter den #endifs gehen natürlich in Ordnung.
Die Einrückungen der #include-Anweisungen (mittels tabs?) machen den Code zwar lesbarer, aber ich bin nicht sicher, ob jeder C-Compiler das frißt...

Aber ich glaube, auch VS kann mit der etwas weniger lesbaren Version leben.

Das Schwierigste: Ich habe weder VS noch LabView zur Verfügung. Mir ist nicht klar, was man Dritten zur Verfügung stellen muß danit sie:
1. das vorkompilierte LabView-Modul nutzen können.
2. Im Sinne von open source dieses selbst erstellen können. Die speziellen LabView-header dürfte ich wahrscheinlich nicht in die Distribution aufnehmen, da NI die Rechte hat.
Andererseits reicht einem LabView-Anwender ja der hinweis, wo er sie hinzupacken hat.

Noch eine Frage, weil ich Labview nicht kenne. Habe immer nur die Bilder gesehen, bei denen mit grafischen Symbolen Datenfluß-orientiert "programmiert" wird: Wie kann in LabView eine unterbrochene Verbindung wiederaufgebaut werden?
Z.B. nach Ziehen des MPI.-Adapters?

Damit die Diskussion hier im Forum nicht den Rahmen sprengt und wir leichter Dateien austauschen können, wäre es vielleicht gut, wenn du meine normale Mailadresse (auf der libnodave-Seite angegeben) benutzt.


----------



## Gerhard Bäurle (14 März 2005)

Mahlzeit,

es gibt natürlich auch die Möglichkeit, eine Bibliothek 
einzusetzen, in die LabVIEW fix und fertig integriert ist:

AGLink
MHJ

Gut, ist weder kostenfrei noch open source, aber vielleicht 
trotzdem interessant, da fertig.

Viele Grüße

Gerhard Bäurle


----------



## Anonymous (14 März 2005)

Hallo zusammen!

Ich arbeite auch mit VS.Net allerdings auf C#. Wollte mir zunächst mit hilfe von  libnodave ein kleines Testproggi schreiben. Bin dabei aber schnell an meine Grenzen gestoßen (Dll-Import) . 
Mein Hauptproblem ist das ich net genau weis, wie alle Methoden heissen bzw. deren genaue "Aufrufstrukturen" sind. Habe zwar ein paar Einfache entschluesselt, allerdings wenns komplexer wird is Schluß. 

Wär nett wenn ihr mir helfen könntet 

Thx vorab 

Bewareofthis

--->   Beware@2die4.com


----------



## Zottel (14 März 2005)

Wie die Funktionen (Methoden? sind doch für Objekte.) heißen:

Das Testprogramm testMPI.c benutzt die wichtigsten. Schmeiß einfach aus main alles raus, was mit optionen eingeschaltet wird. Dann bleibt ein ziemlich kleines Programm übrig. Die wichtigsten sind:

di=daveNewInterface(...)
daveInitAdapter(di)
dc=daveNewConnection(di,...)

connectPLC(dc)
daveReadBytes(dc, ...);

Das reicht eigentlich für.den 1. Test

Ansonsten müßtest du etwas gezielter fragen.


----------



## Zottel (14 März 2005)

Hier der Minimaltest für MPI:


----------



## Anonymous (15 März 2005)

Hallo und Thx,
also ich arbeite ja mit c#.net , also muß ich  per Dll-Import  auf Libnodave zugreifen. Das Hauptprob dabei ist, die Definitionen der einzelnen Typen bzw. Konstanten. Da Libnodave OpenSource is, ist es auf jeden Fall machbar. Hab mich in die Header-Files eingelesen und hab wie gesagt Einige einfache Funktionen "entschluesselt", so daß ich  in meinem c# Proggi auf die Libnodave-Dll zugreifen kann. Schwierig wirds, wenn die Definitionen komplexer werden 
Bsp. aus der Libnodave-Docu:

 daveInterface * di;
    di =daveNewInterface(fds, "IF1", localMPI, daveProtoXXX, daveSpeedYYY);

Die Struktur daveInterface is so dekl.:

struct _daveInterface {
    _daveOSserialType fd; /* some handle for the serial interface */
    int users;		/* a counter used when multiple PLCs are accessed via */
			/* the same serial interface and adapter. */
    int localMPI;	/* the adapter's MPI address */
    char * name;	/* just a name that can be used in programs dealing with multiple */
			/* daveInterfaces */
    int timeout;	/* Timeout in microseconds used in transort. */
    int protocol;	/* The kind of transport protocol used on this interface. */
    int speed;		/* The MPI or Profibus speed */
    int ackPos;		/* position of some packet number that has to be repeated in ackknowledges */
    int nextConnection;
    _initAdapterFunc initAdapter;		/* pointers to the protocol */
    _connectPLCFunc connectPLC;			/* specific implementations */
    _disconnectPLCFunc disconnectPLC;		/* of these functions */
    _disconnectAdapterFunc disconnectAdapter;
    _exchangeFunc exchange;
    _sendMessageFunc sendMessage;
    _getResponseFunc getResponse;
    _listReachablePartnersFunc listReachablePartners;
};

Hier sind also mehrere Strukturen usw. definiert.  

Um Libnodave nutzen zu können muß ich doch die Struktur "_daveInterface"
bei mir im Programm nochmals definieren, oder gibt´s ne andere Möglichkeit?

MfG

Bewareofthis


----------



## Anonymous (15 März 2005)

Hallo und Thx,
also ich arbeite ja mit c#.net , also muß ich  per Dll-Import  auf Libnodave zugreifen. Das Hauptprob dabei ist, die Definitionen der einzelnen Typen bzw. Konstanten. Da Libnodave OpenSource is, ist es auf jeden Fall machbar. Hab mich in die Header-Files eingelesen und hab wie gesagt Einige einfache Funktionen "entschluesselt", so daß ich  in meinem c# Proggi auf die Libnodave-Dll zugreifen kann. Schwierig wirds, wenn die Definitionen komplexer werden 
Bsp. aus der Libnodave-Docu:

 daveInterface * di;
    di =daveNewInterface(fds, "IF1", localMPI, daveProtoXXX, daveSpeedYYY);

Die Struktur daveInterface is so dekl.:

struct _daveInterface {
    _daveOSserialType fd; /* some handle for the serial interface */
    int users;		/* a counter used when multiple PLCs are accessed via */
			/* the same serial interface and adapter. */
    int localMPI;	/* the adapter's MPI address */
    char * name;	/* just a name that can be used in programs dealing with multiple */
			/* daveInterfaces */
    int timeout;	/* Timeout in microseconds used in transort. */
    int protocol;	/* The kind of transport protocol used on this interface. */
    int speed;		/* The MPI or Profibus speed */
    int ackPos;		/* position of some packet number that has to be repeated in ackknowledges */
    int nextConnection;
    _initAdapterFunc initAdapter;		/* pointers to the protocol */
    _connectPLCFunc connectPLC;			/* specific implementations */
    _disconnectPLCFunc disconnectPLC;		/* of these functions */
    _disconnectAdapterFunc disconnectAdapter;
    _exchangeFunc exchange;
    _sendMessageFunc sendMessage;
    _getResponseFunc getResponse;
    _listReachablePartnersFunc listReachablePartners;
};

Hier sind also mehrere Strukturen usw. definiert.  

Um Libnodave nutzen zu können muß ich doch die Struktur "_daveInterface"
bei mir im Programm nochmals definieren, oder gibt´s ne andere Möglichkeit?

MfG

Bewareofthis


----------



## Zottel (15 März 2005)

Drei Gedanken, da ich gerade selbst nicht klar sehe:

1. Ich kenne C# nicht. Da es ein C-Derivat ist, würde ich vermuten, daß es C-header files einbinden kann. Bei C++ wäre zusätzlich nötig:

extern "C" {
#include "nodave.h"
}

Das ist nötig, damit C++ es wie "normales" C behandelt und ein paar ++-Erweiterungen nicht anzuwenden versucht. Etliche header files anderer Bibliotheken haben das "extern "C" { " und "}" schon als erste und letzte (verarbeitete) Zeile eingebaut. Libnodave hat das nicht. Das liegt daran, daß ich die Möglichkeit offen halten wollte, es auf möglichst vielen Compilern zu übersetzen, also auch solche, die wegen ihres Alters (DOS) oder weil sie für Systeme gemacht sind, die kein C++ kennen (8051, AVR), nix von C++ wissen.
Damit ich klarer sehe: Kann C# C-header includen? Ist das ein gewöhnlicher Weg?

2. Normalerweise braucht das Anwenderprogramm von der inneren Struktur von daveInterface absolut keine Ahnung zu haben. Durch einbinden des headers wird sie ihm aber bekannt. Die Funktionszeiger braucht wohl kein Anwenderprogramm der Welt. Aber die Bibliothek braucht sie, um verschiedene Protokolle großenteils gleich aber an entscheidenden Stellen verschieden zu behandeln. Ein einfaches Anwenderprogramm (in C) sollte auch funktionieren, wenn man ihm eine vereinfachte header-Datei unterschöbe, in der daveInterface einfach mit void gleichgesetzt würde. Das sollte solange gut gehen, wie nicht versucht wird, auf interne Felder vn daveInterface zu zugreifen. Die einzig interessanten Felder für ein Anwenderprogramm sind timeout, falls jemand feststellt, das die Antwort von seiner CPU länger dauert und der Name, wenn jemand mit mehreren Verbindungen gleichzeitig arbeiten würde (ja, das geht!).
Es könnte eine vereinfachte header-Datei geben, die nur diese Felder "zeigt". Aber ich will ja nicht zwei header pflegen und zueinander passend halten. C++ kann sowas mit einem header file, indem "#pragma interface" die Sichtbarkeit einschränkt.

3. Dem C#-Compiler liegen doch ganz sicher irgendwelche Beispiele bei, wie auf Standard-DLLs zugegriffen wird. Schick mir ein kleines, damit ich sehe, was da anders ist.


----------



## Anonymous (15 März 2005)

Hallo,

C# kann die Header-Files nicht einbinden, da es auf den .Net Framework aufbaut. Will man Funktionen ausserhalb des Frameworks (z.B. weitere Windows-Funktionen) nutzen muß man sich mit Dll-Aufrufe rumschlagen (P/Invoke). Um Libnodave nutzen zu können muß ich auf die Funktionen der kompilierten Dll zurueckgreifen. Die Definitionen sind ja dann leider nicht bekannt . . .

Gruß 

Bewareofthis


----------



## Zottel (15 März 2005)

Ok, mit ein bischen googlen weiß ich jetzt, daß C# keine header einbindet. Wie es nun geht, weiß ich auch nicht. Es könnte gehen, daß du die "komplizierten" Funktionszeiger-Felder einfach wegläßt. Erstens brauchst du nicht auf sie zuzugreifen und zweitens besorgt sich Libnodave den Speicher selbst, so daß deine Anwendung auch die Größe nicht kennen muß.

Wenn man die Bibliothek in C# neu schreiben wollte, sollte das ähnlich wie in JAVA gehen. Dafür habe ich eine Version geschrieben. Dort gibt es ein Objekt namens PLCInterface, daß nichts spezielles kann. ListReachablePartners ist eine "leere" methode. Das davon abgeleitete MPIinterface überschreibt die Methode und tut was.

S7Connection ist eine abstrakte Verbindung zur S7, die Datenpakete zusammenstellen und analysieren aber nicht versenden oder empfangen kann. Dazu überschreibt dann MPIConnection die abstrakten Methoden. 
Das sind dann genau die Dinge, die in C über Funktionszeiger abgewickelt würden.

Natürlich könnte auch JAVA über JNI auf die .DLL zugreifen. Das würde darauf hinauslaufen, daß es ein "Wrapper"-Objekt Methoden hat, die einzelne Funktionen der DLL aufrufen. Soweit ich mich erinnere, würde eine weitere .dll in C erstellt, die die Methoden des Wrapper-Objekts enthält. Sie schafft die Übernahme und Übergabe von Daten an JAVA indem jni.h eingebunden wird.

Da sähe dann so aus:

Eine vorhandene nuetzlich.DLL enthält die fuktion tuDies().
Der header nuetzlich.h definiert sie als int tuDies(float).

Um tuDies(). in JAVA zu nutzen braucht es eine weitere .DLL jNuetzlich.dll

Der Code sähe ungefähr so aus:

```
#include "jni.h"
#include "nuetzlich.h"

jinteger JtuDies(jfloat jf) {
	float f;
        int i;
	jinteger ji;
	f=fromJfloat(jf);	 // heißt nicht genauso, aber im Prinzip eine Routine aus JNI, die
					//  den Wert für C aus der JAVA-Variablen "extrahiert"
	i=tuDies(f);		// Aufruf der eigentlichen Funktion
	ji=jIntfromC(i);		// in eine JAVA-Variable packen
	return ji;
}
```
Das wäre mit einem C-Compiler zur neuen .DLL Jnuetzlich.dll zu verarbeiten.

Auf der JAVA Seite nun das Wrapper-Objekt:

```
public class Nuetzlich {
	public static native int jtuDies(float f); 
}
```
Eine andere Klasse ruft nun Nuetzlich.jtuDies() auf.

Lange Rede, kurzer Sinn: Ich stelle mir vor, daß das in C# ähnlich ist? Muß mir mal am W.E. Mono reintun...

[/code]


----------



## Anonymous (15 März 2005)

Hab mal die Definitionen verfolgt, wenn ich das alles nachbilde, hab ich im Prinzip alles neu geschríeben.
Funktionert das, wenn ich nur "Blanko-Strukturen" definiere und die dann in den Aufrufen übergebe? Denke mal net.

Gruß

Bewareofthis

P.S.:
Daher war mir "Zottel" ein Begriff :
-->http://www.mycsharp.de/wbb2/thread.php?threadid=4451

 :wink:


----------



## Zottel (15 März 2005)

Anonymous schrieb:
			
		

> Hab mal die Definitionen verfolgt, wenn ich das alles nachbilde, hab ich im Prinzip alles neu geschríeben.
> Funktionert das, wenn ich nur "Blanko-Strukturen" definiere und die dann in den Aufrufen übergebe? Denke mal net.
> 
> Gruß
> ...


Doch, zum Teil funktioniert es mit Blanko-Strukturen. Habe es gerade probiert, allerdings mit reinem C unter LINUX. Ich kann das testMPImin.c kompilieren, wenn im header nix anderes steht als


```
struct _daveInterface {
	_daveOSserialType fd;
}
```
daveConnection kann ich auch so ähnlich verkürzen.

Das klappt für das Minmalprogramm. Mit den anderen Testprogrammen kriege ich Probleme, weil sie aus daveConnection die Felder AnswLen, resultPointer, maxPDUlen nutzen.

In diesem Fall müssen auch die dazwischen liegenden Felder erhalten bleiben, damit der "abstand" der Felder zum Beginn der Struktur noch stimmt.
Insofern ist nodave.h nicht für solche Vereinfachung "optimiert". Dann stünden die von außen benötigten Felder vorne.
Natürlich könnte man die Lücken durch gleich lange Felder von bytes oder sonstigem schließen.

Was mir noch zu denken gibt: Ich habe gesehen, dß C# struct kennt, im Gegensatz zu JAVA.
Ist ein in C# definiertes Struct automatisch genauso lang wie ein in C definiertes? Aber wenn nicht, wie sollte es dann überhaupt gehen?

Das das mit dem "Verkürzen" klappt, liegt daran, daß das Anwendungsprogramm je nur einen Zeiger auf daveInterface oder daveConnection bekommt und auch nur diesen Zeiger wieder beim Aufruf angibt. Im Grunde also einfach nur ein 32-bit-wert. Sowohl das Anlegen der Strukturen als auch der Zugriff auf die Bestandteile geschehen (fast, Ausnahmen oben) nur innerhalb des Bibliothekscodes.
Was natürlich nicht gehen kann, ist die Bibliothek selbst mit dem "vereinfachten" header zu übersetzen, sonst wäre er auch überflüssig.


----------



## Zottel (16 März 2005)

Im Anhang eine "verkürzte" Version von nodave.h. Alles was zwischen 
#ifdef COMPLETE
und
#endif 
steht, egal ob Felder, #defines oder ganze structs, braucht die Minimalanwendung testMPImin.c nicht zu kennen. 

Anbei noch diese URL:
http://msdn.microsoft.com/library/d...us/csref/html/vcwlkplatforminvoketutorial.asp

War nach meiner unmaßgeblichen Meinung das beste, was ich bei google heute gefunden habe.


----------



## Anonymous (21 März 2005)

Thx Zottel 

werd mich mal darüber machen bei gelegenheit.
Hab jetz noch ori. Prodave bekommen das scheint zu funktionieren.
Allerdings hab ich bisher noch keine so komplexen Strukturen gefunden wie bei Libnodave.

Gruss

Bewareofthis


----------



## Zottel (21 März 2005)

Die "komplexe" Struktur in daveInterface (6 oder 7 Zeiger auf Funktionen) sorgt dafür, daß du z.B auf eine 200 mit denselben Funktionen zugreifen kannst, wie auf die 300 und 400. Bei Prodave brauchst du dafür andere Funktionen. 
Sie sorgt ebenso dafür, daß du mit dem Parameter "protocol" das Übertragungsprotokoll wählen kannst. Prodave benutzt, soweit ich weiß, einen Haufen von Registry-Einträgen, die bei der Installation verschiedener Siemens-Software angelegt mittels des Controls "PC-PG-Schnittstelle einstellen" verändert werden. Das ist, alles zusammengenommen, weit komplexer und es ist nicht auf andere Betriebssysteme übertragbar. 
Als Konsequenz benötigt Libnodave eben auch keine Installation und hat eine weit höhere Chance, auch unter der nächsten Version von Windows zu laufen. Schau dir an, wie viele Beiträge sich alleine hier damit beschäftigen, daß irgendeine Version von Step7 auf irgendeiner Version von Windows bescheuerte Fehler erzeugt und wieviel Zeit (hoffentlich) gut bezahlte Leute mit dieser Scheiße verbringen!
Ganz zuletzt: Wie die verkürzte header-Datei zeigt, könnte ein Teil der Komplexität vor der Anwendung "versteckt" werden. Um das möglichst weit treiben zu können, müßte lediglich die Reihenfolge der Elemente in ein paar structs verändert werden. Es scheint mir aber eher dem Geist von "open source" angemessen, dem Benutzer Zugriff auf einfach alles zu geben. Auch die Funktionen, die mit einem _ anfangen, sind alle im Header aufgeführt, obwohl der "Normalanwender" sie nicht braucht.
Vielleicht findet der ein oder andere User ja eine nützliche Anwendung dafür...


----------

