Libnodave getXXXfrom()

Olli0285

Level-1
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich hab Mal wieder ein Problem mit Libnodave.

Ich wollte die getS32from(buf) benutzen, um einen DINT aus einem DB zu lesen, jedoch ist die Funktion im Wrapper nicht implementiert.

Mein Aufruf:
Private Declare Function daveGetS32from Lib "libnodave.dll" (ByRef buffer as Byte) as Integer

Variable= daveGetS32from(buf)

Fehler:
die funktion konnte in der dll nicht gefunden werden.

Vielleicht ist der Aufruf falsch.

Wäre schön wenn jemand etwas weiß!

VB.net
Libnodave 0.8.4.5

MfG

Olli
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Jochen,

wie alt ist denn der Wrapper? ich hab letzte Woche deine aktuelleste Version runtergeladen! Ich weiß nur nicht wie man die fehlenden funktion von Libnodave in das VB Projekt implementiert.
Ich lese in einem Sub vier Buffer Arrays aus und ich weiß nicht ob dann die Zeigerfunktion mit getS32at(buf) das richtige array benutzt. Ich poste gerne Mal den ganzen Code wenn es hilft. Mit der Bitabfrage funktioniert alles.

Das Problem ist das ich aus den Bytes keinen 4Byte langen Integer kriege. Das Auslesen in den Buffer funktioniert problemlos

Ich denke es hängt am:

Privat Function........

Ich weiß es aber nicht!

MfG

Olli
 
Zuletzt bearbeitet:
Hallo Jochen,

wie alt ist denn der Wrapper? ich hab letzte Woche deine aktuelleste Version runtergeladen! Ich weiß nur nicht wie man die fehlenden funktion von Libnodave in das VB Projekt implementiert.
Ich lese in einem Sub vier Buffer Arrays aus und ich weiß nicht ob dann die Zeigerfunktion mit getS32at(buf) das richtige array benutzt. Ich poste gerne Mal den ganzen Code wenn es hilft. Mit der Bitabfrage funktioniert alles.

Das Problem ist das ich aus den Bytes keinen 4Byte langen Integer kriege. Das Auslesen in den Buffer funktioniert problemlos

Ich denke es hängt am:

Privat Function........

Ich weiß es aber nicht!

MfG

Olli

JO poste mal Code....

Aber wie gesagt mit meiner Connection Lib kannst du mehrer Variablen einfach in ein Array Packen und dann einfach alle auf einmal lesen lassen.

Bsp:

Code:
private List<LibNoDaveValue> myValues = new List<LibNoDaveValue>();

myValues.Add(new LibNoDaveValue
                                   {
                                       LibNoDaveDataSource = LibNoDaveDataSource.Datablock,
                                       ByteAddress = 10 ,
                                       BitAddress = 0,
                                       DatablockNumber = 1,
                                       ArraySize = 0,
                                       LibNoDaveDataType = LibNoDaveDataType.Dword
                                   });
myValues = myConn.ReadValues(myValues);

Und schon sind alle Werte in der myValues Liste gelesen (hier nur db1.dbd10)
 
Mein Code:

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

Dim bufi(2) As Byte 'buffer inputs
Dim bufo(0) As Byte 'buffer outputs
Dim buff(0) As Byte 'buffer merker^^^^
Dim bufdb(21) As Byte 'buffer DB
Dim a123 As Integer

dc.readBytes(daveInputs, 0, 0, 3, bufi) 'Eingänge laden
dc.readBytes(daveOutputs, 0, 0, 1, bufo) 'Ausgänge laden
dc.readBytes(daveFlags, 0, 0, 1, buff) 'Merker laden
dc.readBytes(daveDB, 10, 0, 21, bufdb) 'Datenbaustein laden

If bufi(0) And 64 Then 'E0.6
PStanzeOben.Location = New Point(446, 259)
Else : PStanzeOben.Location = New Point(446, 274)
End If
If bufi(0) And 128 Then 'E0.7
PKlemmehi.Location = New Point(PBoxVorschub.Location.X, PKlemmehi.Location.Y)
PBoxVorschub.Location = New Point(225, 291)
ElseIf bufi(1) And 1 Then 'E1.0
PKlemmehi.Location = New Point(PBoxVorschub.Location.X, PKlemmehi.Location.Y)
PBoxVorschub.Location = New Point(158, 291)
End If
If bufi(1) And 2 Then 'E1.1
PBand1.Visible = True
PBand2.Visible = True
Else
PBand1.Visible = False
PBand2.Visible = False
End If
If bufi(1) And 4 Then 'E1.2
LblSiKe.Visible = False
Else
LblSiKe.Visible = True
End If
If bufi(2) And 16 Then 'E2.4 Autobetrieb
LblGruSte.ForeColor = Color.LightGray
LblAuto.BackColor = Color.Lime
LblEinr.BackColor = Color.Gray
LblAutoStart.ForeColor = Color.Black
LblEinzel.ForeColor = Color.LightGray
LblAutoStop.ForeColor = Color.Black
ElseIf bufi(2) And 32 Then 'E2.5 Einrichtbetrieb
LblAuto.BackColor = Color.Gray
LblEinr.BackColor = Color.Lime
LblEinzel.ForeColor = Color.Black
LblAutoStart.ForeColor = Color.LightGray
LblAutoStop.ForeColor = Color.LightGray
LblGruSte.ForeColor = Color.Black

Else 'Drehschalter Mittelstellung
LblGruSte.ForeColor = Color.LightGray
LblAuto.BackColor = Color.Gray
LblEinr.BackColor = Color.Gray
LblEinzel.ForeColor = Color.LightGray
LblAutoStart.ForeColor = Color.LightGray
LblAutoStop.ForeColor = Color.LightGray
End If
If bufo(0) And 4 Then
LblMotStart.ForeColor = Color.LightGray
LblMotStop.ForeColor = Color.Black
Else
LblMotStart.ForeColor = Color.Black
LblMotStop.ForeColor = Color.LightGray
End If
If bufo(0) And 8 Then
PBoxWickel.Visible = True
Else
PBoxWickel.Visible = False
End If
If bufo(0) And 32 Then
PKlemmeVo.Location = New Point(372, 267)
Else
PKlemmeVo.Location = New Point(372, 259)
End If
If bufo(0) And 64 Then
PKlemmehi.Location = New Point(PBoxVorschub.Location.X, 267)
Else
PKlemmehi.Location = New Point(PBoxVorschub.Location.X, 259)
End If
If buff(0) And 1 Then 'M0.0 Länge ein\aus
CheckBoxLaenge.Checked = True
Else
CheckBoxLaenge.Checked = False
End If
If buff(0) And 2 Then 'M0.1 Länge ein\aus
CheckBoxLaenge.Checked = True
Else
CheckBoxLaenge.Checked = False
End If


End Sub

Bis hierhin funktioniert alles ich ahbe aber in der bufDB() noch verschiedene Werte die ich auslesen möchte.


DB
0 S5t
2 DINT
6DINT
10INT
12INT
14 S5T
16 INT

Für diesen zweck bräuchte ich die gets16from bzw. die gets32from Funktion.

MfG

Olli
 
Also bei mir ist die Funktion public static int getS32from(byte[] b, int pos) in meiner libnodave.net definiert!
Die Funktionen getXXfrom() sind aus folgendem Grund NICHT in den Interfaces für .NET, VB(A), PERL usw. enthalten:
Diese Sprachen kennen keine Zeiger im Sinne von C und Pascal (Zeiger ist eine Adresse im Speicher, ab dieser Adresse aufwärts existiert ein prinzipiell unbeschränkt langer, fortlaufender und byteweise adressierbarer Speicher, das Hochzählen der Adresse erfolgt in gleicher Weise in C und der Zielsprache).
getXXfrom() setzt voraus, daß mittels readDaveBytes(...,buffer) ein Zeiger auf einen Puffer übergeben wurde, von dem später gelesen werden kann. Auch das setzt schon die Existenz von Zeigern voraus.

Es mag z.Z. funktionieren, kann aber auch in der nächsten Variante von .NET in die Hose gehen.

Die .NET-Sprachen wurden mit dem Ziel entwickelt, der Laufzeitumgebung möglichst viel Kontrolle über das Speichermanagement zu geben.

Wenn man unbedingt mit Byte-Arrays in .NET arbeiten möchte, kann dieses in sauberer Art so erreicht werden:
1. benutze daveReadBytes ohne Puffer, d.h. mit null als letztem Parameter.
2. lies die Bytes mit daveGetBytes byteweise aus und lege sie im Ziel-Array ab.
3. Wiederhole diesen Vorgang, anstatt daveReadManyBytes aus der DLL zu benutzen.
4. Auf dieses Array können nun .NET-Varianten von getXXfrom() angewandt werden, die libnodave allerdings nicht mitbringt.
 
Die Funktionen getXXfrom() sind aus folgendem Grund NICHT in den Interfaces für .NET, VB(A), PERL usw. enthalten:
Diese Sprachen kennen keine Zeiger im Sinne von C und Pascal (Zeiger ist eine Adresse im Speicher, ab dieser Adresse aufwärts existiert ein prinzipiell unbeschränkt langer, fortlaufender und byteweise adressierbarer Speicher, das Hochzählen der Adresse erfolgt in gleicher Weise in C und der Zielsprache).
getXXfrom() setzt voraus, daß mittels readDaveBytes(...,buffer) ein Zeiger auf einen Puffer übergeben wurde, von dem später gelesen werden kann. Auch das setzt schon die Existenz von Zeigern voraus.

Es mag z.Z. funktionieren, kann aber auch in der nächsten Variante von .NET in die Hose gehen.

Die .NET-Sprachen wurden mit dem Ziel entwickelt, der Laufzeitumgebung möglichst viel Kontrolle über das Speichermanagement zu geben.

Wenn man unbedingt mit Byte-Arrays in .NET arbeiten möchte, kann dieses in sauberer Art so erreicht werden:
1. benutze daveReadBytes ohne Puffer, d.h. mit null als letztem Parameter.
2. lies die Bytes mit daveGetBytes byteweise aus und lege sie im Ziel-Array ab.
3. Wiederhole diesen Vorgang, anstatt daveReadManyBytes aus der DLL zu benutzen.
4. Auf dieses Array können nun .NET-Varianten von getXXfrom() angewandt werden, die libnodave allerdings nicht mitbringt.

Aber die getS32from ist doch in der libnodave.net enthalten (nicht als dll deklaration sondern als .net funktion). Und wenn er noch meine neueere libnodave.net verwendet, dann sind sogar noch ein paar mehr drin!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
hallo,

dass die Funktion in der dll nicht gefunden wird, ist seltsam.

Bei der Deklaration der daveGetS32from-Funktion ist die Groß- und Kleinschreibung zu beachten. Schreibst Du daveGets16from, kommt eine Fehlermeldung "Einstiegspunkt in dll nicht gefunden...".

Du kannst auch mal den Versuch machen, die libnodave.dll ins System32 von Windows und außerdem, wenn Du in der Testumgebung von VB.Net arbeitest, in Bin/Debug des aktuellen Projekts zu legen. Ich weiß nicht, wo die libnodave.dll überall automatisch gesucht wird.

Gruß
Earny
 
ich hab Mal wieder ein Problem mit Libnodave.

Ich wollte die getS32from(buf) benutzen, um einen DINT aus einem DB zu lesen, jedoch ist die Funktion im Wrapper nicht implementiert.

Mein Aufruf:
Private Declare Function daveGetS32from Lib "libnodave.dll" (ByRef buffer as Byte) as Integer

Variable= daveGetS32from(buf)


DINT ist doch Double Int.
Int ist 32 Bit lang
DINT wäre dann 64 Bit lang.

Falls das bis hier nicht stimmt, ignorier bitte folgendes:

Du kannst das Ergebnis doch auch aus dem Puffer lesen
und ihn den gewünschten Datentyp konvertieren.

angenommen:

dc.davereadbytes(libnodave.davedb, 1, 0, 4, Puffer)
Puffer muss halt ein Array von der Mindestgröße 4 sein.

dannach:
convert.toint64(Puffer[0])

und schon hast du den Inhalt des Datenblocks 1 an der Stelle
0 gelesen und in den Datentyp DoubleInt konvertiert.

GetS32 ist daher überflüssig. Ich verwende es bei meinem Programm nicht.
Ich konvertiere das gelesene direkt in aus dem Lesepuffer in den gewünschten Datentyp ;-)

lg Marco*
 
DINT ist doch Double Int.
Int ist 32 Bit lang
DINT wäre dann 64 Bit lang.

Falls das bis hier nicht stimmt, ignorier bitte folgendes:

Du kannst das Ergebnis doch auch aus dem Puffer lesen
und ihn den gewünschten Datentyp konvertieren.

angenommen:

dc.davereadbytes(libnodave.davedb, 1, 0, 4, Puffer)
Puffer muss halt ein Array von der Mindestgröße 4 sein.

dannach:
convert.toint64(Puffer[0])

und schon hast du den Inhalt des Datenblocks 1 an der Stelle
0 gelesen und in den Datentyp DoubleInt konvertiert.

GetS32 ist daher überflüssig. Ich verwende es bei meinem Programm nicht.
Ich konvertiere das gelesene direkt in aus dem Lesepuffer in den gewünschten Datentyp ;-)

lg Marco*

in s7 ist ein dint 32 bit und ein normaler int 16 bit (die größe eines int's ist nicht vorgeschrieben, das ist architektur und programmiersprachen abbhänig!)

und was bringt dein convert?? da habe ich ein byte in ein int64 verwandelt! aber wenn er doch einen dint von der sps lesen will muss er ja 4 bytes gemeinsam umtauschen!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
in s7 ist ein dint 32 bit und ein normaler int 16 bit (die größe eines int's ist nicht vorgeschrieben, das ist architektur und programmiersprachen abbhänig!)

und was bringt dein convert?? da habe ich ein byte in ein int64 verwandelt! aber wenn er doch einen dint von der sps lesen will muss er ja 4 bytes gemeinsam umtauschen!

und da libnodave ja auch unter mono auf einer anderen plattform laufen könnte musser beim umtauschen auch noch die bytereihenfolge (Endianes) beachten!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo habe das Problem grade in der anderen Richtung (schreiben, statt lesen) bei meinem VB.NET Proggi. Die die Funktionen libnodave.putU32() und libnodave.putS32() verursachen beim Ausführen eine Speicherbereichsverletzung "Der Index war außerhalb des Arraybereichs.". Ist dies hier wie von Zottel argumentiert in der Pointer Problematik von .NET begründet oder hat dies eine andere Ursache?
Hab das Problem nun folgendermassen gelöst, doch wollte ich verstehen weshalb es zu diesem Fehler kommt.

Problemcode:
Public testbuffer(220) AsByte
...
libnodave.putU32at(testbuffer, 0, intValue)
...

So gehts nun:
Case"DWord"
tempBuffer = BitConverter.GetBytes(intValue)
Buffer(0) = tempBuffer(3)
Buffer(1) = tempBuffer(2)
Buffer(2) = tempBuffer(1)
Buffer(3) = tempBuffer(0)
'libnodave.putU32at(testbuffer, 0, intValue)
res = dc.writeBytes(nArea, nDBnr, nByteAdr, nDataLength, Buffer)

Zusatzfrage: gibt es eigentlich auch eine Funktion libnodave.putU8() oder s.ä. oder wurde darauf verzichtet, da es sich nur um ein Byte handelt und sich die Byteausrichtung der CPU etc. hier nicht drauf auswirkt, bzw der Datentyp "Byte" ohnehin vozeichenlos ist?

Gruss,

bool
 
Hallo habe das Problem grade in der anderen Richtung (schreiben, statt lesen) bei meinem VB.NET Proggi. Die die Funktionen libnodave.putU32() und libnodave.putS32() verursachen beim Ausführen eine Speicherbereichsverletzung "Der Index war außerhalb des Arraybereichs.". Ist dies hier wie von Zottel argumentiert in der Pointer Problematik von .NET begründet oder hat dies eine andere Ursache?
Hab das Problem nun folgendermassen gelöst, doch wollte ich verstehen weshalb es zu diesem Fehler kommt.

Problemcode:
Public testbuffer(220) AsByte
...
libnodave.putU32at(testbuffer, 0, intValue)
...

So gehts nun:
Case"DWord"
tempBuffer = BitConverter.GetBytes(intValue)
Buffer(0) = tempBuffer(3)
Buffer(1) = tempBuffer(2)
Buffer(2) = tempBuffer(1)
Buffer(3) = tempBuffer(0)
'libnodave.putU32at(testbuffer, 0, intValue)
res = dc.writeBytes(nArea, nDBnr, nByteAdr, nDataLength, Buffer)

Zusatzfrage: gibt es eigentlich auch eine Funktion libnodave.putU8() oder s.ä. oder wurde darauf verzichtet, da es sich nur um ein Byte handelt und sich die Byteausrichtung der CPU etc. hier nicht drauf auswirkt, bzw der Datentyp "Byte" ohnehin vozeichenlos ist?

Gruss,

bool

Die putU32 at ist doch in der libnodave.net.dll fast genau so implementiert! Ich denke die mit nur einem Bytes gibt es nicht, da man ein byte einfach direkt in dem array zuweisen kann, bei den anderen funktionen muss halt wieder die endianess beachtet werden!
 
Die putU32 at ist doch in der libnodave.net.dll fast genau so implementiert!

... und doch gibt es die Speicherverletzung ...


Habe grad mal einen Blick in den Sourcecode der libnodave.net.dll gewagt und siehe da ...die Betonung liegt hier auf "fast":

public static void putU32at(byte[] b, int pos, int value)
{
byte[] bytes = BitConverter.GetBytes(Convert.ToUInt32(value));
if (BitConverter.IsLittleEndian)
{
b[pos + 3] = bytes[0];
b[pos + 2] = bytes[1];
b[pos + 1] = bytes[2];
b[pos] = bytes[4];
}
else
Array.Copy(bytes, 0, b, pos, 4);
}

Ich vermute das "bytes[4]" musste "bytes[3]" heissen oder liege ich hier falsch?

Das selbe giltet übrigens auch für die Funktion "putS32at".

Gruss,

bool
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich vermute das "bytes[4]" musste "bytes[3]" heissen oder liege ich hier falsch?

Das selbe giltet übrigens auch für die Funktion "putS32at".

scheint wohl tatsächlich "bytes[3]" heissen zu müssen. Habs grad in der cs geändert und neu compiliert, jetzt gehts auch ohne Speicherverletzung ;)

Gruss,

bool
 
Habe da noch ein weiteres Problem festgestellt.

Wenn die Fuktion "putS16at" aufgerufen wird und ein Wert >32767 übergeben wird, gibt es ein exeption error, da angeblich durch "0" geteilt wird ebenso bei Verwendng eine negativen Zahl in Verbindung mit der Funktion "putU16at".

GGf. sollten die Funktionen soweit "gehärtet" werden, dass die exeptions vermieden werden können. Vielleicht würde es hier dann Sinn machen wenn über einen Rückgabewert ein Fehlercode (z.B. "-1" oder FALSE) übergeben wird.

Die Frage wäre evtl. auch, ob die Konvertierung in INT16 bzw UINT16 vorab in den Funktionen nötig ist. Es werden ohnehin Funktionsintern nur die entsprechenden Bytes kopiert.

Gruss,

bool
 
Habe da noch ein weiteres Problem festgestellt.

Wenn die Fuktion "putS16at" aufgerufen wird und ein Wert >32767 übergeben wird, gibt es ein exeption error, da angeblich durch "0" geteilt wird ebenso bei Verwendng eine negativen Zahl in Verbindung mit der Funktion "putU16at".

GGf. sollten die Funktionen soweit "gehärtet" werden, dass die exeptions vermieden werden können. Vielleicht würde es hier dann Sinn machen wenn über einen Rückgabewert ein Fehlercode (z.B. "-1" oder FALSE) übergeben wird.

Die Frage wäre evtl. auch, ob die Konvertierung in INT16 bzw UINT16 vorab in den Funktionen nötig ist. Es werden ohnehin Funktionsintern nur die entsprechenden Bytes kopiert.

Gruss,

bool

Hab das nun auch geändert, und die 16 Bit Funktionen so angepasst das sie einen short oder ushort zurückgeben oder erwarten. Ich denke, den Funktionen sollte auch nur der Datentyp übergeben werden, den Sie handeln können!
 
Zurück
Oben