2010-11-30 46 views
3

Nous avons obtenu le travail OPC. Je ne peux pas installer RsLinx sur mon Win7 (et le mode XP aussi) à cause d'erreurs, donc j'envoie mon application de test à l'endroit réel, et quelqu'un le testant.Delphi - Problème de passage de variant OLE (RsLinx OPC, Ajout de groupe fonctionnant uniquement avec des constantes)

Parce que je n'ai pas de DLL, je ne peux pas faire d'interface Delphi, donc j'ai besoin de faire des appels OLE seulement.

J'ai eu un problème intéressant avec Group Add.

Je le démontrer:

procedure TForm1.Button8Click(Sender: TObject); 
var 
    r, g : variant; 
    s : string; 
    v : variant; 
    ws : WideString; 
begin 
    Log('Connect'); 
    r := CreateOleObject('RSI.OPCAutomation'); 
    r.Connect('RSLinx OPC Server'); 

    Log('Add as constant'); 
    g := r.OPCGroups.Add('MONKEY_C'); 
    Log('Name ' + g.Name); 

    Log('Add as string'); 
    s := 'MONKEY_S'; 
    g := r.OPCGroups.Add(s); 
    Log('Name ' + g.Name); 

    Log('Add as variant'); 
    s := 'MONKEY_V'; 
    v := s; 
    g := r.OPCGroups.Add(v); 
    Log('Name ' + g.Name); 

    Log('Add as ole variant'); 
    s := 'MONKEY_OV'; 
    v := VarAsType(s, varOleStr); 
    g := r.OPCGroups.Add(v); 
    Log('Name ' + g.Name); 

    Log('Add as widestring'); 
    s := 'MONKEY_WS'; 
    ws := WideString(s); 
    g := r.OPCGroups.Add(ws); 
    Log('Name ' + g.Name); 

    Log('Add as widestring var'); 
    s := 'MONKEY_WSV'; 
    ws := WideString(s); 
    v := ws; 
    g := r.OPCGroups.Add(v); 
    Log('Name ' + g.Name); 

    r := 0; 

end; 

Le résultat a été:

Connect 
Add as constant 
Name MONKEY_C 
Add as string 
Name _Group0 
Add as variant 
Name _Group1 
Add as ole variant 
Name _Group2 
Add as widestring 
Name _Group3 
Add as widestring var 
Name _Group4 

Le problème que je ne peux pas ajouter tout groupe que constant défini ...

J'ai besoin de savoir comment Delphi compile cette constante pour que je puisse convertir ma valeur de variant à ce format.

Quelqu'un peut-il m'aider dans ce thème?

Merci: dd


Salut!

Donc le problème est mystérieux. J'ai trouvé une autre erreur dans les appels OLE purs.

function TDDRsOPCObject.IndexOfGroup(GroupName: string): integer; 
var 
    ogs, g : variant; 
    i : integer; 
    s : string; 
begin 
    CheckObject; 
    Result := -1; 
    ogs := FObj.OPCGroups; 
    s := ''; 
    for i := 1 to ogs.Count do begin 
     g := ogs.Item(i); // This is working 
     if AnsiCompareText(g.Name, GroupName) = 0 then begin 
      Result := i; 
      Exit; 
     end; 
    end; 
end; 


function TDDRsOPCObject.GetGroupByName(GroupName: string): variant; 
var 
    idx : integer; 
    ogs, g : variant; 
begin 
    CheckObject; 
    VarClear(Result); 
    idx := IndexOfGroup(GroupName); 
    ogs := FObj.OPCGroups; 
    if idx <> -1 
     then begin 
      g := ogs.Item(idx); // HERE I GOT: The parameter is incorrect 
      Result := g; 
     end; 
end; 

Il est donc intéressant: le IndexOfGroup avec un même appel fonctionne, le GetGroupByName n'est pas ... :-(

Je déterminé que je ne continue pas mon combat avec des moulins à vent (Don Q). Je obtenu TLB d'un cher utilisateur qui ont Delphi7 (en Win7 le Delphi6 ne peut pas produire l'interface OLE), et je trouve Kassl

que ces interfaces peut me aider ...

Merci:. dd

+0

bien n'est pas les groupes constants un moyen de diviser la logique? Je veux dire pouvez-vous ajouter à chaque groupe constant plus de groupes? – ComputerSaysNo

+0

Intéressant. Si je fais ceci: g: = r.OPCGroups.Add (PChar (s) ^); Alors 'M' est passé. – durumdara

+0

Puissions-nous avoir des groupes constants mais je veux comprendre cet enfer OLE ... :-) – durumdara

Répondre

0

Pour autant que je sache, la constante et les chaînes sont toutes converties en OleString/BSTR (WideString). Mais puisque vous avez ces problèmes ... probablement pas.

  1. Que dit la documentation de OPCGroups.Add? Qu'est-ce qui est attendu?
  2. Avez-vous une bibliothèque de types? Peut-être que vous pouvez les importer et utiliser l'interface directement.

Edit:

La documentation est pas très claire.

Il y a quelques choses que vous pouvez essayer:

  1. Vérifiez dans la vue CPU ce que le compilateur Delphi fait du code avec la constante, peut-être que vous voyez quelques conseils là-bas sur ce qu'il faut faire avec vos cordes.
  2. Essayez ce code.
Code

:

const 
    OPC_GROUP_NAME: WideString = 'MONKEY_C'; 
<...> 
    g := r.OPCGroups.Add(OPC_GROUP_NAME); 
    Log('Name ' + g.Name); 

Lorsque ci-dessus fonctionne le code, essayez ceci:

const 
{$J+} //writable constants on 
    OPC_GROUP_NAME: WideString = 'dummy'; 
{$J-} 
<...> 
    OPC_GROUP_NAME := 'MONKEY_BLA'; 
    g := r.OPCGroups.Add(OPC_GROUP_NAME); 
    Log('Name ' + g.Name); //should be: 'Name MONKEY_BLA' 

Note: Je n'aime pas l'étape 2, mais si cela fonctionne .. pourquoi pas. Pour moi, il semble qu'il y ait un bug dans la com-library que vous utilisez.

Edit2:

je regardais le code généré en utilisant la constante et en utilisant une chaîne normale. Avec la constante je vois que l'adresse du premier personnage est poussée sur la pile, avec la chaîne je vois l'adresse d'un pointeur vers une chaîne qui est poussée sur la pile.

Avec le code ci-dessous je peux simuler le même comportement que la constante:

var 
    lWideArray: array[0..40] of WideChar; 
    s: string; 
    i: Integer; 
<..> 
s := 'MONKEY_FOO'; 
for i := 0 to Length(lWideArray) - 1 do 
begin 
    if i < Length(s) then 
    lWideArray[i] := WideChar(s[i+1]) 
    else 
    lWideArray[i] := #0; 
end; 

g := r.OPCGroups.Add(WideString(lWideArray)); 
Log('Name ' + g.Name); 
+0

1. Le document dit: Syntaxe Ajouter (Nom facultatif comme variante) Comme OPCGroup. Donc c'est une variante. Mais je ne sais pas, ce qui signifie, parce que le type de variante n'existe pas dans Delphi (seulement dans les tableaux). – durumdara

+0

2. La bibliothèque de type est inaccessible, parce que je ne peux pas installer RsLinx dans Win7 (en mode XP ne pas installable) ... Ce que je pense que Delphi peut utiliser PWideChar dans le compilateur (interne), mais nous ne pouvons pas l'utiliser Syntaxe OLE. – durumdara

+0

N2.) J'ai essayé votre code, mais seulement le premier travail, avec une constante non modifiable. Cela fonctionne, le prochain (changement de constante) ne l'est pas. – durumdara

0

Il y a quelques problèmes dans votre code, aussi il serait bon de savoir quelle version de Delphi que vous utilisez, et quel type de paramètre utilise l'appel Add(). Quoi qu'il en soit quelques conseils:

ws: = WideString (s);

C'est un mauvais catalogage. Il ne convertira pas votre chaîne en WideString, cela forcera simplement la mémoire à être interprétée comme telle. Utiliser

ws: = s;

La compilation veillera à appeler la routine de conversion.

+0

Salut! Je l'ai essayé: s: = 'MONKEY_WS'; ws: = s; g: = r.OPCGroups.Add (ws); Mais le résultat est faux: "Ajouter en tant que Widetring, Nom _Group0". Donc, la même chose arrive. Je ne sais pas, pourquoi. Et ce que je peux faire pour convertir l'entrée à la même chose que le compilateur faire avec des constantes. – durumdara

+0

Si vous essayez: V: Variante; V: = 'MONKEY_V'; r.OPCGroups.Add (V); ? –

+0

Cette opération d'ajout basée sur une variante ne fonctionne pas. – durumdara

0

Vous n'avez pas besoin d'inventer la roue. Il y a beaucoup de bibliothèques, d'exemples et d'exemples de code pour utiliser OPC avec Delphi. Pour les serveurs et clients Delphi OPC gratuits, regardez ici: http://www.opcconnect.com/delphi.php.