Array-Struktur

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
mkersch
UDF-Programmierer
UDF-Programmierer
Beiträge: 89
Registriert: Fr, 12. Mai 2006 13:26
Wohnort: Wünricht

Array-Struktur

Beitrag von mkersch »

Guten Tage Forenmitglieder,

da ich im Moment mit einem ActiveX Aufruf kämpfe, wende ich mich mit der Bitte um Hilfe an Euch.

Für eine Kommunikation zu einer SPS von Beckhoff verwende ich ein ActiveX.

Im Prinzip funktioniert die Kommunikation.

Code: Alles auswählen

 oXbp_Ax:AdsAmsServerNetId :=  ADS_ID_PRUEFEN
  oXbp_Ax:AdsAmsServerPort := 801
  dummy := oXbp_Ax:AdsCreateVarHandle("var_test", @hVar)  // Handle öffnen

  dummy := oXbp_Ax:AdsSyncReadIntegerVarReq(@hVar ,2, @variable)  // Variable Integer lesen

  oXbp_Ax:AdsDeleteVarHandle(@hVar)   // Handle schließen
Da wir aber ca. 200 Variablen zyklisch lesen müssen, wäre das lesen aus einen Array eleganter.


Die Fa. Beckhoff hat auch ein VBasic Beispielprogramm mitgeliefert.

Code: Alles auswählen

Dim hVar As Long
Dim Data(100) As Integer

'--- wird beim Starten aufgerufen ---
Private Sub Form_Load()
  '--- Exception freigeben --- AdsOcx1.EnableErrorHandling = True
  Call AdsOcx1.AdsCreateVarHandle("Main.PLCVar", hVar)
End Sub

'--- wird beim Beenden aufgerufen ---
Private Sub Form_Unload(Cancel As Integer)
  Call AdsOcx1.AdsDeleteVarHandle(hVar)
End Sub

'--- wird vom Bediener aufgerufen ---
Private Sub cmd_read_Click()
  Dim intIndex As Integer
  '--- Array komplett auslesen ---
  Call AdsOcx1.AdsSyncReadIntegerVarReq(hVar, 200, Data(0))
  '--- Array Elemente in Form anzeigen ---
  lstArray.Clear 
  For intIndex = 0 To 99
    lstArray.AddItem (CStr(intIndex) & Chr(vbKeyTab) & _ CStr(Data(intIndex)))
  Next
End Sub

Wir haben versuch dies in Xbase++ nachzubilden, jedoch beim lesen mit AdsSyncReadIntegerVarReq( tritt ein Laufzeitfehler auf.


Wie kann ich eine Xbase Array so nachbilden, das es einem C oder Vbasic entspricht ?
Wie kann ich dieses Problem lösen ?

mfg.

mkersch
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

mkersch hat geschrieben: Dim hVar As Long
Dim Data(100) As Integer
...
Wie kann ich eine Xbase Array so nachbilden, das es einem C oder Vbasic entspricht ?
Hallo,

ein Array in C oder VB ist eine Kette von Bytes (word, integer, long etc.) die direkt hintereinander liegen.
Darum müssen die auch alle vom gleichen Typ sein.
Ein Xbase++ Array ist im Prinzip eine Kette von Zeigern auf die tatsächlichen Inhalte.
Für ActiveX sollte das eigentlich automatisch umgesetzt werden, aber damit habe ich keine Erfahrungen.

Bei DLL Aufrufen etc. muss man zunächst schauen um was für einen Datentyp es sich handelt.
DATA() wurde mit Integer angegeben, hVAR mit Long. Somit denke ich es handelt sich um ein Array von 16 bit Zahlen.
Das ist nichts anderes als

Code: Alles auswählen

cDATA := replicate(chr(0),200) // Buffer 100 Zahlen * 2 Byte pro Zahl = 16 bit
Bei der Übergabe wird dies dann per Referenz übergeben, also

Code: Alles auswählen

...., @cDATA  )
Für das Auslesen, bzw. auch für das Bilden wenn du andere Startwerte als 0 brauchst ...

Code: Alles auswählen

for x := 1 to 100 // ACHTUNG Basic zählt von 0 bis 99
    ? Bin2i( cDATA[x] )
next
Gruß
Hubert
mkersch
UDF-Programmierer
UDF-Programmierer
Beiträge: 89
Registriert: Fr, 12. Mai 2006 13:26
Wohnort: Wünricht

Re: Array-Struktur

Beitrag von mkersch »

Vielen Dank für die Info.



puffer := replicate(chr(0),200) // Buffer 100 Zahlen * 2 Byte pro Zahl = 16 bit

// puffer := space(200)
dummy := oXbp_Ax:AdsSyncReadIntegerReq(@hVar2 ,20, @puffer)
oXbp2:setData(str(test))

bekomme folgende Fehlermeldung-

---------------------------
Xbase++ Fehlermeldung
---------------------------
Fehler Automation/6500
Beschreibung : Typkonflikt.

Parameter hat falschen Typ
Operation : AdsSyncReadIntegerReq
Thread ID : 1
Betriebsystem Fehler : -2147352571
Typkonflikt.
Called from MAIN(120)
---------------------------
OK Abbrechen
---------------------------


mfg.

mkersch
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Hi,

ja ActiveX ... ;-)

was mir auffällt, du schreibst hier direkt ...

Code: Alles auswählen

dummy := oXbp_Ax:AdsSyncReadIntegerReq(@hVar2 ,20, @puffer)
oben steht
Im Prinzip funktioniert die Kommunikation.
oXbp_Ax:AdsAmsServerNetId := ADS_ID_PRUEFEN
oXbp_Ax:AdsAmsServerPort := 801
dummy := oXbp_Ax:AdsCreateVarHandle("var_test", @hVar) // Handle öffnen
dummy := oXbp_Ax:AdsSyncReadIntegerVarReq(@hVar ,2, @variable) // Variable Integer lesen
oXbp_Ax:AdsDeleteVarHandle(@hVar) // Handle schließen
Ich nehme an, dass die umgebenden Befehle auch nötig sind (handle öffnen ...).
Warum wird das hVar2 mehrfach per Referenz übergeben ?
Ich würde nur beim Erstellen des Handles dieses per Referenz übergeben.
Was bedeutet der 2. Parameter ?
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Aus Jimmys Beitrag Array-Daten nach Excel habe ich mal dieses Beispiel herausgeholt:

Code: Alles auswählen

oSheet := oExcel:Worksheets( 1 ):cells
oSheet:range( "A1:B255" ):value      := aExcel
wie man sieht, wandelt die Xbase++ ActiveX Aufrufe so um, dass es passt.
Eventuell muss man das bei deinem Bespiel auch so machen, wobei ich bei dir noch
gar nicht gesehen habe wie du dein ActiveX Objekt bildest.

Da soll es auch 2 Möglichkeiten geben, aber wie geschrieben bin ich kein ActiveX Profi.
Im ActiveX Beispiel zu RMChart könnte man auch nach der Syntax sehen, die müssen auch
Arrays übergeben. Das nutze ich aber auch nicht.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Hi,

dieser Artikel könnte etwas Licht in die Sache bringen, ganz unten verweist Jimmy auf einen Artikel in der Alaska Newsgroup bezüglich ActiveX und Array Parameter.

http://www.xbaseforum.de/viewtopic.php?f=28&t=369
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Array-Struktur

Beitrag von AUGE_OHR »

mkersch hat geschrieben:dummy := oXbp_Ax:AdsSyncReadIntegerReq(@hVar2 ,20, @puffer)
Es ist meistens nicht möglich mehrere Parameter an ein activeX "so" zu übergeben.
verwende stattdessen SetProperty (oder callMethod() ) dann kann du auch 3 Parameter übergeben.

Code: Alles auswählen

oXbp_Ax:setProperty("AdsSyncReadIntegerReq",@hVar2 ,20, @puffer) 
oder bei Method
oXbp_Ax:callMethod("AdsSyncReadIntegerReq",@hVar2 ,20, @puffer)
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

AUGE_OHR hat geschrieben:

Code: Alles auswählen

oXbp_Ax:setProperty("AdsSyncReadIntegerReq",@hVar2 ,20, @puffer) 
oder bei Method
oXbp_Ax:callMethod("AdsSyncReadIntegerReq",@hVar2 ,20, @puffer)
Hi Jimmy,

übergibt man also Arrray Parameter wie bei DLLs oder müsste man es so machen ?

Code: Alles auswählen

aPuffer := array(100) // 100 Variablen
oXbp_Ax:setProperty("AdsSyncReadIntegerReq",@hVar2 ,20, @aPuffer) 
oder bei Method
oXbp_Ax:callMethod("AdsSyncReadIntegerReq",@hVar2 ,20, @aPuffer)
und warum den Handle auch per Referenz ?
Gruß
Hubert
mkersch
UDF-Programmierer
UDF-Programmierer
Beiträge: 89
Registriert: Fr, 12. Mai 2006 13:26
Wohnort: Wünricht

Re: Array-Struktur

Beitrag von mkersch »

Vielen Dank für Eure Hilfe,

habe sämtliche Programmvariationen getestet, funktionier leider nicht.

Ich bekomme immer den Fehler Typkonflikt.

Ich denke das Problem liegt beim Xbase-Array.




Nachfolgen nochmals ein Delphi Beispiel (von der Fa. Beckhoff)

Beispiel:

Code: Alles auswählen

PROGRAM MAIN
VAR
	varIntArray :ARRAY[1..9] OF INT:=9(1);
END_VAR


Delphi Programm:

Array aus der SPS lesen:

Code: Alles auswählen

procedure TForm1.SyncReadArrayVarButtonClick(Sender: TObject);
var i, hVar, AdsResult:integer;
    varIntArray       : ARRAY[1..9] OF Smallint;
begin
    AdsResult := AdsOcx1.AdsCreateVarHandle( 'MAIN.VARINTARRAY', hVar );
    if AdsResult = 0 then
    begin
        AdsResult := AdsOcx1.AdsSyncReadIntegerVarReq( hVar, sizeof(varIntArray), varIntArray[1] );
        if AdsResult = 0 then
        begin
            ListBox1.Clear();
            for i:=1 to 9 do
                ListBox1.Items.Add( Format('varIntArray[%d] = %d', [i, varIntArray[i]] ) );
        end
        else Label1.Caption := Format('AdsSyncReadIntegerVarReq error:%d', [AdsResult] );
        AdsOcx1.AdsDeleteVarHandle( hVar );
    end
    else Label1.Caption := Format('AdsCreateVarHandle error:%d', [AdsResult] );
end;
mfg.

mkersch
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Hi,

also so wie ich diese Zeile verstehe ...

Code: Alles auswählen

AdsSyncReadIntegerVarReq( hVar, sizeof(varIntArray), varIntArray[1] )
muss folgende Parameter übergeben:
hVar = Handle den man beim Öffnen erhalten hat
sizeof(varIntArray) = Anzahl der Bytes im Speicher ! Also nicht die Anzahl der Variblen
varIntArray[1] = Referenz auf das erste Element

somit wäre folgendes zu setzen:

Code: Alles auswählen

nHandle := ????
nAnzahlIntVar := 100
// eventuell I2bin() gegen w2bin() tauschen = signed int -> unsigned int (word)
// Pascal varIntArray : ARRAY[1..9] OF Smallint; sind doch 16 bit signed integer oder ???
cPuffer := replicate( I2bin( 0 ) , nAnzahlIntVar )
oXbp_Ax:setProperty("AdsSyncReadIntegerReq",nHandle, len(cPuffer), @cPuffer) 
aber beachten muss man auch diese Zeile
AdsResult := AdsOcx1.AdsCreateVarHandle( 'MAIN.VARINTARRAY', hVar );
hier weiß ich jetzt nicht ob MAIN.VARINTARRAY das aus der MAIN meint, oder Speicher in dem AdsOcx1 meint.
Um was handelt es sich eigentlich bei dem Gerät und gibt es keine DLL Schnittstelle die einfacher ist ? :wink:
Gruß
Hubert
mkersch
UDF-Programmierer
UDF-Programmierer
Beiträge: 89
Registriert: Fr, 12. Mai 2006 13:26
Wohnort: Wünricht

Re: Array-Struktur

Beitrag von mkersch »

Danke für die Info !

Im Prinzip funktioniert das lesen aus der Beckhoff SPS jedoch nur eine Integer nach der anderen.

1. Handle öffnen
2. Variable lesen
3. Handle schließen

Code: Alles auswählen

function lesen(quelle)
local hVar
local variable
local dummy
memvar oXbp_AX,ADS_ID_PRUEFEN
hVar := 0
variable := 0

  oXbp_Ax:AdsAmsServerNetId :=  ADS_ID_PRUEFEN
  oXbp_Ax:AdsAmsServerPort := 801
  dummy := oXbp_Ax:AdsCreateVarHandle(quelle, @hVar)  // Handle öffnen

  dummy := oXbp_Ax:AdsSyncReadIntegerVarReq(@hVar ,2, @variable)

  oXbp_Ax:AdsDeleteVarHandle(@hVar)   // Handle schließen

return(variable)

Will ich ein Array einlesen bekomme ich immer den Laufzeitfehler Typkonflikt.

Auch das letzte Beispiel bringt diesen Fehler.

mfg.

Mkersch
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

mkersch hat geschrieben: Will ich ein Array einlesen bekomme ich immer den Laufzeitfehler Typkonflikt.
Somit ist eindeutig, dass die AktiveX Schnittstelle das intern prüft.
mkersch hat geschrieben: dummy := oXbp_Ax:AdsSyncReadIntegerVarReq(@hVar ,2, @variable)
das zeigt auf jeden Fall, dass eine Variable 2 Byte lang sein muss, also sind es wie gedacht 16bit Integer...
Was passiert wenn du ...

Code: Alles auswählen

local variable
local dummy
local nAnzVar 
memvar oXbp_AX,ADS_ID_PRUEFEN
hVar := 0
nAnzVar  := 100
variable := array(nAnzVar)
afill(variable,0)
  oXbp_Ax:AdsAmsServerNetId :=  ADS_ID_PRUEFEN
  oXbp_Ax:AdsAmsServerPort := 801
  dummy := oXbp_Ax:AdsCreateVarHandle(quelle, @hVar)  // Handle öffnen
  dummy := oXbp_Ax:AdsSyncReadIntegerVarReq(@hVar ,nAnzVar*2, @variable) // oder nur ,nAnzVar*2, variable
  oXbp_Ax:AdsDeleteVarHandle(@hVar)   // Handle schließen
return(variable)
abfragst ?
Bei Fehler probieren ob das besser geht ...
(@hVar ,nAnzVar*2, @variable)
(@hVar ,nAnzVar*2, variable)
(@hVar ,nAnzVar*2, @variable[])
(@hVar ,nAnzVar*2, variable[])
(@hVar ,nAnzVar*2, @variable[1])
(@hVar ,nAnzVar*2, variable[1])

hoffen wir mal dass das nicht zu irgendwelchen abstürzen führt ;-)
Gruß
Hubert
Benutzeravatar
Friedhelm
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 46
Registriert: Sa, 08. Apr 2006 17:20
Wohnort: Leverkusen
Kontaktdaten:

Re: Array-Struktur

Beitrag von Friedhelm »

Hallo zusammen,

Ich habe mich leider etwas später eingeschaltet. Natürlich läßt sich eine Array abrufen, das Problem ist nur das was in in Delphi als "Array[1..9] of integer" angegeben wird, kann man nicht auf ein Array in Xbase anwenden. In Delphi ist eine Array[1..9] of integer ein Zeiger auf eine feste Struktur von 9 Integer-Werten, also 9*32Bit (in Delphi ist ein Integer stardmäßig ein 32-BitInteger). In Xbase habe wir dynamische Arrays, die mit solchen Struturen nichts nichts gemein haben. Wenn die Werte dort ausgelesen werden sollen muß man über einen Binärpuffer gehen:

Code: Alles auswählen

LOCAL cBuffer := Repl(Chr(0), 9*4)
LOCAL aResult     := Array(9)
LOCAL i
   
    // Auslesen der Info in einen Binärpuffer
    oXbp_Ax:CallMethod("AdsSyncReadIntegerReq", @hVar2, 20, @cBuffer)
    // Puffer aus Binärpuffer in Array übernehmen
    FOR i := 1 to 9
         aResult[i] := Bin2L( Subs( @cBuffer, (i-1)*4+ 1,4))
    NEXT
Das Problem ist der Umgang mit der cBuffer Variablen - sobald man eine Operation ohne @Referenzoperator macht, wird die Variable bei Vorkommen eines Chr(0) abeschnitten. daher direkt anwenden wie oben beschrieben.
Gruß Friedhelm
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Hi Friedhelm,

der Zugriff bezieht sich aber auf die Variable "varIntArray : ARRAY[1..9] OF Smallint;",
daher gehen wir von 16 Bit Integer aus. Den Binar-puffer hatten wir auch schon,
aber laut der Fehlermeldung will das ActiveX nicht akzeptieren, wohl weil Alaska selbst da eine Umsetzung macht ... :?

Auf jeden Fall muss man den 2. Paramter von fix 20 auf die Länge des Puffers abändern:

Code: Alles auswählen

oXbp_Ax:CallMethod("AdsSyncReadIntegerReq", @hVar2, len(cBuffer), @cBuffer)
PS:

vermutlich geht euch die Abfrage von 100 Einzelwerten zu langsam (weiß ich nicht).
Wenn es nicht anders geht, solltet Ihr z.B. Delphi nehmen und eine DLL generieren.
Mit dieser fragt Ihr dann die vielen Elemente ab und erzeugt ein Delphi-Array wie gewünscht.
Dieses kann man dann aus Xbase++ per cPuffer abholen.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array-Struktur

Beitrag von brandelh »

Hallo

ich habe jetzt mal oben die CODE Tags gesetzt, bitte immer beachten !

Es ist so mühsam Quellcode ohne CODE Tags zu lesen ... und so einfach diese zu setzen:

1. Text markieren
2. Schaltfläche CODE klicken ...
Gruß
Hubert
mkersch
UDF-Programmierer
UDF-Programmierer
Beiträge: 89
Registriert: Fr, 12. Mai 2006 13:26
Wohnort: Wünricht

Re: Array-Struktur

Beitrag von mkersch »

Hallo Forenmitglieder,

Entschuldigung für die verspätetet Rückmeldung (hatte Urlaub).


Ich habe sämtlichen Version durchprobiert. Leider bekomme ich immer noch den Fehler Typkonflikt.

Ich denke ich muss die Variablen einzeln lesen (kein Array benützen) dies ist zwar der umständliche Weg, aber er funktioniert wenigstens.


Nochmal vielen Dank für Eure Mithilfe .

mfg.

mkersch
Antworten