Delphi - проблема передачи варианта OLE (RsLinx OPC, групповое добавление, работающее только с константами) - PullRequest
3 голосов
/ 30 ноября 2010

Мы получили работу OPC.Я не могу установить RsLinx на свой Win7 (и режим XP тоже) из-за ошибок, поэтому я отправляю свое тестовое приложение в реальное место, и кто-то тестирует его.

Поскольку у меня нет DLL, я не могу сделатьИнтерфейс Delphi, поэтому мне нужно только выполнять OLE-вызовы.

У меня возникла интересная проблема с добавлением группы.

Я демонстрирую это:

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 не ...: - (

Так что ярешил, что я не продолжаю свои бои с ветряными мельницами (Дон Q). Я получил TLB от дорогого пользователя, у которого есть Delphi7 (в Win7 Delphi6 не может создать интерфейс OLE), и я нашел Kassl.

Может эти интерфейсы могутпомогите мне ...

Спасибо: дд

Ответы [ 3 ]

0 голосов
/ 30 ноября 2010

В вашем коде есть некоторые проблемы, также было бы неплохо узнать, какую версию Delphi вы используете, и какой тип параметра использует вызов Add (). В любом случае некоторые намеки:

ws: = WideString (s);

Это неправильный тип. Он не будет преобразовывать вашу строку в WideString, он просто заставит память интерпретироваться как таковую. Используйте

ш: = с;

Компиляция позаботится о том, чтобы вызвать процедуру преобразования.

0 голосов
/ 01 декабря 2010

Вам не нужно изобретать колесо. Есть много библиотек, примеров и примеров кода, как использовать OPC с Delphi. Бесплатные серверы и клиенты Delphi OPC можно найти здесь: http://www.opcconnect.com/delphi.php.

0 голосов
/ 30 ноября 2010

Насколько я знаю, константа и строки все преобразуются в OleString / BSTR (WideString). Но так как у вас есть эти проблемы ... вероятно, нет.

  1. Что говорит документация OPCGroups.Add? Что ожидается?
  2. У вас есть библиотека типов? Может быть, вы можете импортировать их и напрямую использовать интерфейс.

Edit:

Документация не очень ясна.

Есть несколько вещей, которые вы можете попробовать:

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