代码之家  ›  专栏  ›  技术社区  ›  durumdara

delphi-ole变量传递问题(rslinx opc,组添加,仅使用from常量)

  •  3
  • durumdara  · 技术社区  · 14 年前

    我们得到了OPC工作。由于出现错误,我无法将rslinx安装到我的win7(和xp模式),因此我将测试应用程序发送到实际位置,并由某人进行测试。

    因为我没有动态链接库,我不能做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不是…:

    所以我决定不再继续和风车作战(唐Q)。 我从一个拥有Delphi7(在Win7中Delphi6不能生成OLE接口)的亲爱的用户那里得到了TLB,我找到了kassl。

    希望这些接口能帮助我…

    谢谢: DD

    3 回复  |  直到 14 年前
        1
  •  0
  •   The_Fox    14 年前

    据我所知,常量和字符串都被转换为olestring/bstr(widestring)。但既然你有这些问题…大概不会。

    1. 操作组的文档说明了什么?期望是什么?
    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'
    

    注意:我不喜欢第二步,但如果它有效的话……为什么不。在我看来,你使用的COM库中有一个bug。

    编辑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);
    
        2
  •  0
  •   user160694    14 年前

    您的代码中有一些问题,而且很高兴知道您使用的Delphi的版本,以及add()调用使用的参数类型。总之,一些提示:

    wS:=宽字符串;

    那是一个错误的排版。它不会将字符串转换为宽字符串,它只会强制将内存解释为宽字符串。使用

    WS:= S;

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

        3
  •  0
  •   avra    14 年前

    你不必发明轮子。在Delphi中使用opc有很多库、示例和示例代码。有关免费Delphi OPC服务器和客户端,请查看以下内容: http://www.opcconnect.com/delphi.php .

    推荐文章