Delphi - OLE 变量传递问题(RsLinx OPC,仅使用常量进行组添加)

发布于 2024-10-05 07:56:48 字数 2652 浏览 0 评论 0原文

我们得到了 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如何编译这个常量我可以将我的变量值转换为这种格式。

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

谢谢: 嗨


所以这个问题很神秘。 我在纯 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

We got OPC job. I cannot installed RsLinx to my Win7 (and XP mode too) because of errors, so I send my test app to the real place, and somebody testing it.

Because I don't have DLL, I cannot make Delphi interface, so I need to do OLE Calls only.

I got an interesting problem with Group Add.

I demonstrate it:

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;

The result was:

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

So the problem that I cannot add any Group than constant defined...

I need to know HOW Delphi compile this constant to I can convert my variant value to this format.

Can anybody help me in this theme?

Thanks:
dd


Hi!

So the problem is mysterious.
I found another errors in the pure OLE calls.

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;

So it is interesting: the IndexOfGroup with same call is working, the GetGroupByName is not... :-(

So I determined I do not continue my fighting with windmills (Don Q).
I got TLB from a dear user that have Delphi7 (in Win7 the Delphi6 cannot produce OLE interface), and I found Kassl.

May these interfaces can help me...

Thanks:
dd

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

说不完的你爱 2024-10-12 07:56:48

据我所知,常量和字符串都转换为 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 库似乎存在错误。

Edit2:

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

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

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);

As far as I know the constant and the strings are all converted to an OleString/BSTR (WideString). But since you are having these problems... probably not.

  1. What does the documentation of OPCGroups.Add say? What is expected?
  2. Do you have a type library? Maybe you can import them and use the interface directly.

Edit:

The documentation isn't very clear.

There are a few things you can try:

  1. Check in CPU view what the Delphi compiler made of the code with the constant, maybe you see some hints there about what to do with your strings.
  2. Try this code.

code:

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

When above code works, try this:

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: I don't like step 2, but if it works.. why not. To me it seems like there is a bug in the com-library you use.

Edit2:

I looked at the code generated by using the constant and using a normal string. With the constant I see the address of the first character being pushed on the stack, with the string I see the address of a pointer to a string being pushed on the stack.

With the code below I can simulate the same behaviour as with the constant:

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);
寒江雪… 2024-10-12 07:56:48

您的代码中存在一些问题,最好知道您正在使用哪个版本的 Delphi,以及 Add() 调用使用什么参数类型。无论如何,一些提示:

ws := WideString(s);

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

ws := s;

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

There are some issues in your code, also it would be nice to know which version of Delphi you're using, and what parameter type the Add() call use. Anyway some hints:

ws := WideString(s);

That's a wrong typecast. It won't convert your string to a WideString, it will just force the memory to be interpreted as such. Use

ws := s;

The compile will take care to call the conversion routine.

不爱素颜 2024-10-12 07:56:48

你不必发明轮子。有很多库、示例和示例代码如何在 Delphi 中使用 OPC。对于免费的 Delphi OPC 服务器和客户端,请查看此处:http://www.opcconnect.com/delphi。 php.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文