3

我们得到了 OPC 工作。由于错误,我无法将 RsLinx 安装到我的 Win7(和 XP 模式),所以我将我的测试应用程序发送到真实的地方,并有人对其进行测试。

因为我没有DLL,所以我不能做Delphi接口,所以我只需要做OLE调用。

Group Add 遇到了一个有趣的问题。

我演示一下:

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;

结果是:

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

所以我不能添加任何组而不是常量定义的问题......

我需要知道 Delphi 如何编译这个常量,以便我可以将我的变量值转换为这种格式。

有人可以帮我解决这个主题吗?

谢谢:dd


你好!

所以这个问题很神秘。我在纯 OLE 调用中发现了另一个错误。

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;

所以有趣的是:具有相同调用的 IndexOfGroup 正在工作,GetGroupByName 不是...... :-(

所以我决定不再和风车战斗(Don Q)。我从一个有 Delphi7 的亲爱的用户那里得到了 TLB(在 Win7 中,Delphi6 不能产生 OLE 接口),我找到了 Kassl。

希望这些接口可以帮助我...

谢谢:dd

4

3 回答 3

0

您的代码中存在一些问题,也很高兴知道您使用的是哪个版本的 Delphi,以及 Add() 调用使用的参数类型。无论如何一些提示:

ws := WideString(s);

这是一个错误的类型转换。它不会将您的字符串转换为 WideString,它只会强制将内存解释为这样。利用

ws := s;

编译将注意调用转换例程。

于 2010-11-30T19:41:04.333 回答
0

据我所知,常量和字符串都转换为 OleString/BSTR (WideString)。但既然你有这些问题......可能不会。

  1. OPCGroups.Add 的文档是怎么说的?期望什么?
  2. 你有类型库吗?也许您可以导入它们并直接使用界面。

编辑:

文档不是很清楚。

您可以尝试以下几件事:

  1. 在 CPU 视图中查看 Delphi 编译器对带有常量的代码所做的事情,也许你会在那里看到一些关于如何处理字符串的提示。
  2. 试试这个代码。

代码:

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

当上面的代码工作时,试试这个:

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'

注意:我不喜欢第 2 步,但如果它有效.. 为什么不呢。对我来说,您使用的com-library 中似乎存在错误。

编辑2:

我查看了使用常量和使用普通字符串生成的代码。使用常量,我看到第一个字符的地址被压入堆栈,而字符串我看到指向被压入堆栈的字符串的指针的地址。

使用下面的代码,我可以模拟与常量相同的行为:

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);
于 2010-11-30T19:37:29.490 回答
0

You do not have to invent the wheel. There are a lot of libraries, examples and sample code how to use OPC with Delphi. For free Delphi OPC servers and clients, take a look here: http://www.opcconnect.com/delphi.php.

于 2010-12-01T11:22:38.333 回答