Discussion:
SafeArray zu OleVariant übergeben?
(zu alt für eine Antwort)
Stefan Koschke
2009-11-12 08:04:22 UTC
Permalink
Hallo zusammen,

nach 2 Tagen verzweifeltem Suchen komme ich immer noch nicht weiter :-(
Eine Procedure soll OleVariant zurückgeben:

procedure Ttestform.Read_ID(out Mtr_ID: OleVariant);
var
PS : PSafeArray;
rgsa: Array[0..0] of TSafeArrayBound;
begin
rgsa[0].cElements:= 5;
rgsa[0].lLbound:= 0;
PS := SafeArrayCreate(VT_BSTR,2,rgsa);
//hier soll nun PS an Mtr_ID übergeben werden aber wie???

end;
Kann mir jemand bitte weiterhelfen?

Ciao
Stefan
Michael Winter
2009-11-12 09:56:08 UTC
Permalink
Post by Stefan Koschke
procedure Ttestform.Read_ID(out Mtr_ID: OleVariant);
var
PS : PSafeArray;
rgsa: Array[0..0] of TSafeArrayBound;
begin
rgsa[0].cElements:= 5;
rgsa[0].lLbound:= 0;
PS := SafeArrayCreate(VT_BSTR,2,rgsa);
//hier soll nun PS an Mtr_ID übergeben werden aber wie???
end;
Hilft der Verweis auf die Funktion VarArrayCreate in der Unit Variants (D7)?

-Michael
NineBerry Schwarz
2009-11-12 09:55:27 UTC
Permalink
Hallo
Post by Stefan Koschke
procedure Ttestform.Read_ID(out Mtr_ID: OleVariant);
var
PS : PSafeArray;
rgsa: Array[0..0] of TSafeArrayBound;
begin
rgsa[0].cElements:= 5;
rgsa[0].lLbound:= 0;
PS := SafeArrayCreate(VT_BSTR,2,rgsa);
//hier soll nun PS an Mtr_ID übergeben werden aber wie???
end;
Kann mir jemand bitte weiterhelfen?
Verwende VarArrayCreate statt SafeArrayCreate

Neun
Stefan Koschke
2009-11-12 10:19:49 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
procedure Ttestform.Read_ID(out Mtr_ID: OleVariant);
var
PS : PSafeArray;
rgsa: Array[0..0] of TSafeArrayBound;
begin
rgsa[0].cElements:= 5;
rgsa[0].lLbound:= 0;
PS := SafeArrayCreate(VT_BSTR,2,rgsa);
//hier soll nun PS an Mtr_ID übergeben werden aber wie???
end;
Kann mir jemand bitte weiterhelfen?
Verwende VarArrayCreate statt SafeArrayCreate
Neun
Hallo Neun,

vielen Dank, zu VarArrayCreate bin ich auch schon gekommen, das läßt
sich nun einem OleVariant zuweisen.
Was mir aber fehlt ist nun einem Eintrag in einem solchen Array den
Inhalt eines Records zuzuweisen:

type ID = record
code : string;
inhalt : integer;
werte : array[0..5] of double;
end;
...
var
m : ID;
...
Mtr_ID := VarArrayCreate([0,99], varVariant);
m.code := 'irgendwas';
m.inhalt := 12345;
m.werte[0] := 123.45;
...
Mtr_ID[0] := m; << das geht nicht :-(

Ciao
Stefan
Michael Winter
2009-11-12 10:42:08 UTC
Permalink
Post by Stefan Koschke
Was mir aber fehlt ist nun einem Eintrag in einem solchen Array den
type ID = record
code : string;
inhalt : integer;
werte : array[0..5] of double;
end;
...
var
m : ID;
...
Mtr_ID := VarArrayCreate([0,99], varVariant);
m.code := 'irgendwas';
m.inhalt := 12345;
m.werte[0] := 123.45;
...
Mtr_ID[0] := m; << das geht nicht :-(
VarArrayLock liefert einen Zeiger auf den Anfang des Datenbereichs. Das
folgende Beispiel legt ein OleVariant der erforderlichen Länge an und
füllt den Inhalt mit einem AnsiString:

function StringToOleVariant(const Str: String): OleVariant;
var
P: Pointer;
begin
Result := VarArrayCreate([0, Length(Str) - 1], varByte);
P := VarArrayLock(Result);
Move(Str[1], P^, Length(Str));
VarArrayUnlock(Result);
end;

-Michael
NineBerry Schwarz
2009-11-12 10:47:46 UTC
Permalink
Hallo
Post by Michael Winter
VarArrayLock liefert einen Zeiger auf den Anfang des Datenbereichs. Das
folgende Beispiel legt ein OleVariant der erforderlichen Länge an und
Es sieht wohl so aus, dass der Anwender der Automatisierungsbibliothek
ein relativ unerfahrener Visual Basic - Programmierer ist.

Man sollte die Schnittstelle also möglichst einfach und vollständig im
Rahmen der von COM vorgesehenen Mechanismen gestalten.

Neun
Stefan Koschke
2009-11-12 11:02:56 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Es sieht wohl so aus, dass der Anwender der Automatisierungsbibliothek
ein relativ unerfahrener Visual Basic - Programmierer ist.
Man sollte die Schnittstelle also möglichst einfach und vollständig im
Rahmen der von COM vorgesehenen Mechanismen gestalten.
Neun
Hallo Neun,

viel schlimmer ;-)
Ich soll ein OCX nach Kundenforderung erstellen. Um dies testen zu
können, baue ich natürlich auch die Gegenseite zum OCX parallel.
Die Kundenforderung ist, z.B. ein Array (Load_ProfileS) mit folgendem
Aufbau aus dem OCX auszugeben:

Load_ProfileS : array of Load_Profile;

type Load_Profile = record
Date : Mtr_DateTime;
Channel_Value : array of longint;
end;

Und da scheitere ich seit etlichen Tagen dran :-(

Ciao
Stefan
NineBerry Schwarz
2009-11-12 11:08:52 UTC
Permalink
Hallo
Post by Stefan Koschke
Ich soll ein OCX nach Kundenforderung erstellen. Um dies testen zu
können, baue ich natürlich auch die Gegenseite zum OCX parallel.
Die Kundenforderung ist, z.B. ein Array (Load_ProfileS) mit folgendem
Load_ProfileS : array of Load_Profile;
type Load_Profile = record
Date : Mtr_DateTime;
Channel_Value : array of longint;
end;
Das ist schlicht unmöglich.

Neun
Stefan Koschke
2009-11-12 11:15:59 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
Ich soll ein OCX nach Kundenforderung erstellen. Um dies testen zu
können, baue ich natürlich auch die Gegenseite zum OCX parallel.
Die Kundenforderung ist, z.B. ein Array (Load_ProfileS) mit folgendem
Load_ProfileS : array of Load_Profile;
type Load_Profile = record
Date : Mtr_DateTime;
Channel_Value : array of longint;
end;
Das ist schlicht unmöglich.
Neun
toll :-(
Und wie könnte die Anforderung dann (falls ich sie falsch verstanden
habe) gemeint sein und umgesetzt werden?

Ciao
Stefan
NineBerry Schwarz
2009-11-12 11:20:25 UTC
Permalink
Hallo
Post by Stefan Koschke
toll :-(
Und wie könnte die Anforderung dann (falls ich sie falsch verstanden
habe) gemeint sein und umgesetzt werden?
Ich denke mal, der Kunde ist selbst mit diesen Einschränkungen von COM
nicht vertraut.

Siehe auch mein anderes Posting für mögliche Lösungen.

Neun
Stefan Koschke
2009-11-12 11:26:10 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
toll :-(
Und wie könnte die Anforderung dann (falls ich sie falsch verstanden
habe) gemeint sein und umgesetzt werden?
Ich denke mal, der Kunde ist selbst mit diesen Einschränkungen von COM
nicht vertraut.
Siehe auch mein anderes Posting für mögliche Lösungen.
Hallo Neun,

diese OCX-Geschichte hat meines Wissens folgenden Hintergrund:
Es gibt irgendwo im Ausland eine Software, die mit Meßgeräten kommuniziert.
Jeder hersteller eines Meßgerätes, welches da unterstützt werden soll,
muß ein ocx liefern, welches die geforderten Schnittstellen hat und dann
diese auf das eigene Meßgerät übersetzt anwendet.
Daher gehe ich davon aus, daß es ocx'e anderer Hersteller gibt (auf die
ich leider keinen Zugriff habe) die dies so wie gefordert umsetzen.

Dein anderes Posting mit den Lösungsvorschlägen habe ich gelesen, aber
genau aus o.g. Gründen weiß ich nicht ob da Weg1 auf die Anforderung
bezogen, der richtige ist.

Ciao
Stefan
NineBerry Schwarz
2009-11-12 11:28:40 UTC
Permalink
Hallo
Post by Stefan Koschke
Es gibt irgendwo im Ausland eine Software, die mit Meßgeräten kommuniziert.
Jeder hersteller eines Meßgerätes, welches da unterstützt werden soll,
muß ein ocx liefern, welches die geforderten Schnittstellen hat und dann
diese auf das eigene Meßgerät übersetzt anwendet.
Daher gehe ich davon aus, daß es ocx'e anderer Hersteller gibt (auf die
ich leider keinen Zugriff habe) die dies so wie gefordert umsetzen.
In welcher Form liegt dir denn die Anforderung vor? Ideal wäre es, wenn
du eine Typbibliothek hättest, in der die Schnittstelle genau definiert ist.

Neun
Stefan Koschke
2009-11-12 11:37:47 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
Es gibt irgendwo im Ausland eine Software, die mit Meßgeräten kommuniziert.
Jeder hersteller eines Meßgerätes, welches da unterstützt werden soll,
muß ein ocx liefern, welches die geforderten Schnittstellen hat und
dann diese auf das eigene Meßgerät übersetzt anwendet.
Daher gehe ich davon aus, daß es ocx'e anderer Hersteller gibt (auf
die ich leider keinen Zugriff habe) die dies so wie gefordert umsetzen.
In welcher Form liegt dir denn die Anforderung vor? Ideal wäre es, wenn
du eine Typbibliothek hättest, in der die Schnittstelle genau definiert ist.
Hallo Neun,

das wäre ja zu schön um wahr zu sein ;-)
Nein, im Ernst : ich habe ein pdf-File mit der Definition des ocx, so in
der Form :
Function Name : Read_LP
Argument : date : start date, date end date
Result Type : Load_ProfileS

und die Deklaration der Typen
Load_Profile
{
Date : Mtr_Date Time
Channel_Value [j] : Long // Array of values for holding channel-wise
values.
}

Load_ProfileS
{
Load_ Profile [j] // Array of Load Profile record
}


Mtr_DateTime ist als String (yyyy/mm/dd hh:nn:ss) definiert.

Mehr Angaben habe ich nicht :-(

Ciao
Stefan
NineBerry Schwarz
2009-11-12 11:44:46 UTC
Permalink
Hallo
Post by Stefan Koschke
Nein, im Ernst : ich habe ein pdf-File mit der Definition des ocx
Unterliegt das der Geheimhaltung oder könntest du das hier öffentlich
verlinken oder mir persönlich zusenden?
Post by Stefan Koschke
Load_Profile
{
Date : Mtr_Date Time
Channel_Value [j] : Long // Array of values for holding channel-wise
values.
}
Load_ProfileS
{
Load_ Profile [j] // Array of Load Profile record
}
Mtr_Date Time sollte eigentlich ein WideString sein. Das ist der Typ,
der in COM verwendet wird.

Wo kommt j her? Kann es sein, dass j eine Konstante ist? Wenn es in der
Schnittstelle nur Arrays mit konstanter Länge gibt, sehe ich weniger ein
Problem.

Neun
Stefan Koschke
2009-11-12 11:56:51 UTC
Permalink
Hallo Neun,
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
Nein, im Ernst : ich habe ein pdf-File mit der Definition des ocx
Unterliegt das der Geheimhaltung oder könntest du das hier öffentlich
verlinken oder mir persönlich zusenden?
Du hast Post :-)
Post by NineBerry Schwarz
Post by Stefan Koschke
Load_Profile
{
Date : Mtr_Date Time
Channel_Value [j] : Long // Array of values for holding
channel-wise values.
}
Load_ProfileS
{
Load_ Profile [j] // Array of Load Profile record
}
Mtr_Date Time sollte eigentlich ein WideString sein. Das ist der Typ,
der in COM verwendet wird.
in dem Dokument (solltest es inzwischen haben) steht string :-(
Post by NineBerry Schwarz
Wo kommt j her? Kann es sein, dass j eine Konstante ist? Wenn es in der
Schnittstelle nur Arrays mit konstanter Länge gibt, sehe ich weniger ein
Problem.
j ist allgemein zu verstehen, es word ein Lastgang von Datum x bis
Datumx angefordert was dann ein Array von j Werten ergibt.

Ciao
Stefan
NineBerry Schwarz
2009-11-12 13:12:00 UTC
Permalink
Hallo
Post by Stefan Koschke
Du hast Post :-)
Wenn ich mir das PDF so anschaue, fällt mir zuerst folgendes auf:

Die Rückgabewerte werden als Funktionsergebnisse zurückgegeben, sonder
die Schnittstelle erwartet die Daten in Eigenschaften des eigentlichen
Automatisierungsobjekts.

So scheint die Funktion "Read_ID" die Daten in der Eigenschaft "Mtr_ID"
des Objekts selbst abzulegen. Die Funktionen haben also keinen
Rückgabewert, sondern schreiben die Daten einfach in die Eigenschaften.

Da im Falle eines OCX die Kommunikation ja nicht über Prozessgrenzen
hinweg läuft, können die Daten in ziemlichem Rohformat vorliegen.
Deswegen denke ich mal, die Eigenschaften, wie z.B. "Mtr_ID" sind
letztendlich nur Zeiger auf die eigentlichen Strukturen.

Ich würde hier also einfach einen OleVariant verwenden und diesem als
Zahlenwert die Adresse des Zeigers zuweisen.

Wenn diese Vermutung zutrifft, muss man also gar nicht groß mit
varianten Arrays basteln.

Das eigentliche Problem ist damit aber nicht gelöst. Du musstr trotzdem
wissen, was genau sich die Herrschaften unter einem String vorstellen
und wie Sie erkennen wollen, wieviele Arrays es denn nun gibt.

Ich würde vorschlagen, einfach Mal Kontakt mit dem Hersteller
aufzunehmen (<http://www.aisystemsamr.com>) und dort nachzufragen. Die
haben sicherlich detailliertere Informationen und eventuell sogar etwas
Beispielcode (egal in welcher Sprache).

Neun
Stefan Koschke
2009-11-12 13:43:29 UTC
Permalink
Hallo Neun,
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
Du hast Post :-)
Die Rückgabewerte werden als Funktionsergebnisse zurückgegeben, sonder
die Schnittstelle erwartet die Daten in Eigenschaften des eigentlichen
Automatisierungsobjekts.
wenn Du damit Recht hast, dann wäre die Umsetzung wirklich erheblich
vereinfacht. Aus dieser Sicht habe ich es bisher nicht gesehen!
Post by NineBerry Schwarz
So scheint die Funktion "Read_ID" die Daten in der Eigenschaft "Mtr_ID"
des Objekts selbst abzulegen. Die Funktionen haben also keinen
Rückgabewert, sondern schreiben die Daten einfach in die Eigenschaften.
...welche sich dann einfacher lesen lassen als Ole-Rückgabewerte...
Post by NineBerry Schwarz
Da im Falle eines OCX die Kommunikation ja nicht über Prozessgrenzen
hinweg läuft, können die Daten in ziemlichem Rohformat vorliegen.
Deswegen denke ich mal, die Eigenschaften, wie z.B. "Mtr_ID" sind
letztendlich nur Zeiger auf die eigentlichen Strukturen.
ich habe ein Demo-ocx (unvollständig) von denen ohne Source, das kann
ich mal installieren und testen, ob ich da solche Eigenschalften finde
Post by NineBerry Schwarz
Ich würde hier also einfach einen OleVariant verwenden und diesem als
Zahlenwert die Adresse des Zeigers zuweisen.
versuche ich mal
Post by NineBerry Schwarz
Wenn diese Vermutung zutrifft, muss man also gar nicht groß mit
varianten Arrays basteln.
Das eigentliche Problem ist damit aber nicht gelöst. Du musstr trotzdem
wissen, was genau sich die Herrschaften unter einem String vorstellen
und wie Sie erkennen wollen, wieviele Arrays es denn nun gibt.
ja da kommen schon wieder die Probleme, diese Firma ist für uns kaum
erreichbar (weil Konkurrenz und eigentlich kein Interesse besteht, uns
da zu unterstützen, genaueres kann/darf ich nicht sagen :-( )
Post by NineBerry Schwarz
Ich würde vorschlagen, einfach Mal Kontakt mit dem Hersteller
aufzunehmen (<http://www.aisystemsamr.com>) und dort nachzufragen. Die
haben sicherlich detailliertere Informationen und eventuell sogar etwas
Beispielcode (egal in welcher Sprache).
siehe oben...

Danke für deine Unterstützung, ich versuche mal mit der Variante
Rückgabe als Eigenschaft weiterzukommen.

Ciao
Stefan
NineBerry Schwarz
2009-11-12 14:30:35 UTC
Permalink
Hallo
Post by Stefan Koschke
ich habe ein Demo-ocx (unvollständig) von denen ohne Source, das kann
ich mal installieren und testen, ob ich da solche Eigenschalften finde
Wenn du Glück hast, steckt in dem OCX eine Typelibrary. Dann siehst du
schon mal, wie die Schnittstelle auf oberster Ebene aussieht. Wenn du
möchtest, kannst mir auch das OCX mal senden.

Neun
Stefan Koschke
2009-11-12 15:32:20 UTC
Permalink
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
ich habe ein Demo-ocx (unvollständig) von denen ohne Source, das kann
ich mal installieren und testen, ob ich da solche Eigenschalften finde
Wenn du Glück hast, steckt in dem OCX eine Typelibrary. Dann siehst du
schon mal, wie die Schnittstelle auf oberster Ebene aussieht. Wenn du
möchtest, kannst mir auch das OCX mal senden.
Neun
Hallo Neun,

danke, ja, die habe ich entdeckt und bekomme per Codevervollständigung
auch die Properties sowie Methoden angezeigt. Daher denke ich daß dieses
ocx unvollständig ist, da einige Methoden anders heißen bzw. welche aus
der Anforderung gar nicht enthalten sind.
Aber es hat sich bestätigt, daß nur die Methode Read_LP aufgerufen
werden soll und dann in der Propertie LP_Data das Ergebnis liegt. Dies
ist allerdings wieder OleVariant und enthält, so wie ich das sehe auch
nur einen Zeiger.
Damit haben wir wenigstens die gewünschte Vorgehensweise herausgefunden,
über die Strukturierung der daten die dann dort abgefangen werden können
muß ich mir un Gedanken machen!

Ciao
Stefan

Stefan Koschke
2009-11-12 10:52:03 UTC
Permalink
Post by Michael Winter
Post by Stefan Koschke
Was mir aber fehlt ist nun einem Eintrag in einem solchen Array den
type ID = record
code : string;
inhalt : integer;
werte : array[0..5] of double;
end;
...
var
m : ID;
...
Mtr_ID := VarArrayCreate([0,99], varVariant);
m.code := 'irgendwas';
m.inhalt := 12345;
m.werte[0] := 123.45;
...
Mtr_ID[0] := m; << das geht nicht :-(
VarArrayLock liefert einen Zeiger auf den Anfang des Datenbereichs. Das
folgende Beispiel legt ein OleVariant der erforderlichen Länge an und
function StringToOleVariant(const Str: String): OleVariant;
var
P: Pointer;
begin
Result := VarArrayCreate([0, Length(Str) - 1], varByte);
P := VarArrayLock(Result);
Move(Str[1], P^, Length(Str));
VarArrayUnlock(Result);
end;
-Michael
Hallo Michael,

aus deinem beispiel, welches ein Array of Byte erzeugt, finde ich nicht
heraus, wie ich einen Record da reinpacken könnte?!
Inzwischen bin ich dazu gekommen, nur einen Pointer auf den Record
reinzulegen:
Mtr_ID[0] := ^m;
Das gibt keine Compilerfehler, aber ob das richtig ist?
Auf der empfangenden Seite bekomme ich den Record nämlich nicht wieder
heraus, oder stell mich nur zu dämlich an :-(

Ciao
Stefan
Michael Winter
2009-11-12 11:24:53 UTC
Permalink
Post by Stefan Koschke
aus deinem beispiel, welches ein Array of Byte erzeugt, finde ich nicht
heraus, wie ich einen Record da reinpacken könnte?!
Inzwischen bin ich dazu gekommen, nur einen Pointer auf den Record
Mtr_ID[0] := ^m;
Das gibt keine Compilerfehler, aber ob das richtig ist?
In deinem Fall geht das nicht, weil dein Record einen Zeiger auf einen
Ansi-String enthält. Außerdem müsstest du den Record-Inhalt kopieren
statt nur darauf zu zeigen.

Entweder du benutzt statt dessen einen ShortString oder du denkst die
einen Stream-Mechanismus aus, der die zu übertragenden Daten in einen
Byte-Stream packen kann. Auf der Gegenseite bruachst du natürlich das
entsprechende Gegenstück. Stichworte: TMemoryStream oder TStringStream,
TWriter, TReader.

Das setzt natürlich voraus, dass Du komplette Kontrolle über das
Protokoll hast und auch die Gegenseite selbst implementierst. Ansonsten
siehe Neuns Anmerkungen.

-Michael
Stefan Koschke
2009-11-12 11:30:47 UTC
Permalink
Post by Michael Winter
Post by Stefan Koschke
aus deinem beispiel, welches ein Array of Byte erzeugt, finde ich
nicht heraus, wie ich einen Record da reinpacken könnte?!
Inzwischen bin ich dazu gekommen, nur einen Pointer auf den Record
Mtr_ID[0] := ^m;
Das gibt keine Compilerfehler, aber ob das richtig ist?
In deinem Fall geht das nicht, weil dein Record einen Zeiger auf einen
Ansi-String enthält. Außerdem müsstest du den Record-Inhalt kopieren
statt nur darauf zu zeigen.
Entweder du benutzt statt dessen einen ShortString oder du denkst die
einen Stream-Mechanismus aus, der die zu übertragenden Daten in einen
Byte-Stream packen kann. Auf der Gegenseite bruachst du natürlich das
entsprechende Gegenstück. Stichworte: TMemoryStream oder TStringStream,
TWriter, TReader.
Das setzt natürlich voraus, dass Du komplette Kontrolle über das
Protokoll hast und auch die Gegenseite selbst implementierst. Ansonsten
siehe Neuns Anmerkungen.
Hallo Michael,

ich sehe einen Hoffnungsschimmer am Horizont ;-)
Darf ich aus Deiner Antwort lesen, daß es mit shortstrings anstelle
strings im Record funktionieren könnte?

Folgende Typen sollen im OCX verwendet werden:

type Mtr_DateTime = record
DateTime : string;
end;
Type Mtr_String = record
OBISCode : string;
Value : string;
end;
type Mtr_Data = record
OBISCode : string;
Value : longint;
Scaler : integer;
DateTimeOccure : Mtr_DateTime;
end;
type Mtr_DataS = record
Mtr_Data : array of Mtr_Data;
end;
type Mtr_History = record
Date : Mtr_DateTime;
Mtr_Data : array of Mtr_Data;
end;
type Channel_Definition = record
OBISCode : string;
Scaler : integer;
end;
type Load_Profile_Definition = record
Channel_Definition : array of Channel_Definition;
LPInterval : integer;
LP_Oldest : Mtr_DateTime;
end;
type Load_Profile = record
Date : Mtr_DateTime;
Channel_Value : array of longint;
end;
type Event = record
EventCode : string;
EventName : string;
DateTimeOccure : Mtr_DateTime;
Duration : longint;
Direction : integer;
Magnitude : Double; //real32?
Scaler : integer;
end;
type EventS = record
Event : array of Event;
end;

Wenn ich da mal die Anforderung frei übernehme und statt string
shortstring benutze?
Die Inhalte werden nie über 255 Zeichen lang werden :-)

Ciao
Stefan
Michael Winter
2009-11-12 12:36:48 UTC
Permalink
Post by Stefan Koschke
ich sehe einen Hoffnungsschimmer am Horizont ;-)
Darf ich aus Deiner Antwort lesen, daß es mit shortstrings anstelle
strings im Record funktionieren könnte?
Ja, aber dann steht eben immer eine festa Anzahl Byes an dieser Stelle.
Post by Stefan Koschke
type Mtr_DateTime = record
DateTime : string;
end;
Type Mtr_String = record
OBISCode : string;
Value : string;
end;
Gibt es denn für jeden der Typen, die du jetzt mit "string"
implementierst, nähere Angaben zur Struktur? Strings kann man ja nun in
sehr verschiedener Weise übe den Draht schieben: feste Länge mit
Leerzeichen aufgefüllt, nullterminiert, mit Längenbyte oder -word voran
und und und. Integers übrigens auch.
Post by Stefan Koschke
Wenn ich da mal die Anforderung frei übernehme und statt string
shortstring benutze?
Versuch macht kluch.
Post by Stefan Koschke
Die Inhalte werden nie über 255 Zeichen lang werden :-)
Nie.

-Michael
NineBerry Schwarz
2009-11-12 11:06:51 UTC
Permalink
Hallo
Post by Stefan Koschke
vielen Dank, zu VarArrayCreate bin ich auch schon gekommen, das läßt
sich nun einem OleVariant zuweisen.
Was mir aber fehlt ist nun einem Eintrag in einem solchen Array den
Es ist eigentlich nicht vorgesehen, einfach so einen Record in ein Array
zu packen. Bei COM-Automatisierung arbeitest du über
Programmiersprachengrenzen hinweg. Es ist deswegen notwendig, dass beide
Seiten einen sehr detaillierten Vertrag darüber haben, wie die Daten im
Detail aussehen. Deswegen werden komplexere Datentypen und Methoden in
der Typbibliothek deklariert.

Um dein Problem zu lösen, sehe ich drei Möglichkeiten:

1. Dirty Hack

Verwende eine zweidimensionales Array mit dem Datentyp varVariant. Die
innere Dimension hätte dabei jeweils 8 Einträge, in die die 8 Felder des
Records in vordefinierter Reihenfolge eingetragen werden könnten.

2. Mittelweg

Definiere in der Typbibliothek einen Record-Typ mit den entsprechenden
Feldern. In Schnittstellen können nun leider nicht Arrays dieses Records
verwendet werden, sondern immer nur einzelne Records.

Gib deinem Automatisierungsobjekt eine Methode, mit der man die Anzahl
der Records abfragen kann und eine zweite Methode, die dann einen
konkreten Record anhand des Index im Array zurückgibt.

3. "Richtig"

Du definierst ein eigenes Interface (z.B. "IMyDataRecord"), das die
Daten eines Records definierst. Dem entspricht dann ein Ole-Objekt (z.B.
"TMyDataRecord") in Delphi, das dieses Interface implementiert.

Dann brauchst du noch eine Klasse, die das Interface IEnumVariant
implementiert (z.B. "TMyDataRecordCollection") und ein Array von Records
verwalten kann.

Deine Methode ist dann in der Typbibliothek so deklariert, dass sie ein
IEnumVariant zurückgibt. Intern erzeugt sie ein TMyDataRecordCollection,
füllt dieses mit Daten und gibt dieses Objekt (welches ja die
Schnittstelle TMyDataRecordCollection implementiert) zurück.


Neun
Stefan Koschke
2009-11-12 11:21:48 UTC
Permalink
Hallo Neun,
Post by NineBerry Schwarz
Hallo
Post by Stefan Koschke
vielen Dank, zu VarArrayCreate bin ich auch schon gekommen, das läßt
sich nun einem OleVariant zuweisen.
Was mir aber fehlt ist nun einem Eintrag in einem solchen Array den
Es ist eigentlich nicht vorgesehen, einfach so einen Record in ein Array
zu packen. Bei COM-Automatisierung arbeitest du über
Programmiersprachengrenzen hinweg. Es ist deswegen notwendig, dass beide
Seiten einen sehr detaillierten Vertrag darüber haben, wie die Daten im
Detail aussehen. Deswegen werden komplexere Datentypen und Methoden in
der Typbibliothek deklariert.
1. Dirty Hack
Verwende eine zweidimensionales Array mit dem Datentyp varVariant. Die
innere Dimension hätte dabei jeweils 8 Einträge, in die die 8 Felder des
Records in vordefinierter Reihenfolge eingetragen werden könnten.
gut, das könnte ggf. eine Lösung sein, die der Anforderung nahe kommt,
aber nicht ganz paßt
Post by NineBerry Schwarz
2. Mittelweg
Definiere in der Typbibliothek einen Record-Typ mit den entsprechenden
Feldern. In Schnittstellen können nun leider nicht Arrays dieses Records
verwendet werden, sondern immer nur einzelne Records.
Gib deinem Automatisierungsobjekt eine Methode, mit der man die Anzahl
der Records abfragen kann und eine zweite Methode, die dann einen
konkreten Record anhand des Index im Array zurückgibt.
geht leider nicht, da nur ganz bestimmte Funktionen des ocx gefordert
sind und ich demzufolge keine "Sonderfunktionen" implementieren darf
Post by NineBerry Schwarz
3. "Richtig"
Du definierst ein eigenes Interface (z.B. "IMyDataRecord"), das die
Daten eines Records definierst. Dem entspricht dann ein Ole-Objekt (z.B.
"TMyDataRecord") in Delphi, das dieses Interface implementiert.
Dann brauchst du noch eine Klasse, die das Interface IEnumVariant
implementiert (z.B. "TMyDataRecordCollection") und ein Array von Records
verwalten kann.
Deine Methode ist dann in der Typbibliothek so deklariert, dass sie ein
IEnumVariant zurückgibt. Intern erzeugt sie ein TMyDataRecordCollection,
füllt dieses mit Daten und gibt dieses Objekt (welches ja die
Schnittstelle TMyDataRecordCollection implementiert) zurück.
davon habe ich jetzt absolut nichts verstanden :-(

Ciao
Stefan
Loading...