Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.09.23;
Скачать: CL | DM;

Вниз

SafeArray   Найти похожие ветки 

 
alex_s   (2006-01-11 10:01) [0]

Помогите плиз разобраться со структурой SafeArray.
Мне нужно получить данные c OPC-сервера. Имеем процедуру:

SyncRead(Source:integer; NumItems:integer; var ServerHandles:PSafeArray; out Values:PSafeArray; out Errors:PSafeArray; out Qualities:oleVariant; out TimeStamps:oleVariant);

где Source - источник данных
    NumItems - кол-во считываемых значений

Подскажите, что я делаю не так:

procedure TForm1.Button1Click(Sender: TObject);
var Qual,TimeS:oleVariant;
   A1,A2,A3:oleVariant;
   SH,Val,Err:PSafeArray;
begin
 A1:=VarArrayCreate([0,1],varVariant);
 A1[0]:=My_OPCItem.ServerHandle;
 A2:=VarArrayCreate([0,1],varVariant);
 A3:=VarArrayCreate([0,1],varVariant);
 SH:=PSafeArray(TVarData(A1).VArray);
 Val:=PSafeArray(TVarData(A2).VArray);
 Err:=PSafeArray(TVarData(A3).VArray);
 My_OPCGroup.SyncRead(2,1,SH,Val,Err,Qual,TimeS);
end;

На My_OPCGroup.SyncRead(2,1,SH,Val,Err,Qual,TimeS) выскакивает ошибка.


 
AbrosimovA   (2006-01-11 11:32) [1]

Для получения внятного ответа по-существу требуется указывать текст ошибки.


 
alex_s   (2006-01-11 11:56) [2]

Текст ошибки такой:

Access violation at address 1F506C31 in module "OCSDAAuto.dll".
Read of address 00000058.


 
Набережных С. ©   (2006-01-11 13:02) [3]

А точно элементы массивов должны быть вариантами?
И откуда взята декларация SyncRead? Есть некоторые сомнения в правильности приведенного описания, вот это:

> var ServerHandles:PSafeArray; out Values:PSafeArray; out Errors:PSafeArray

как-то подозрительно выглядит.

А если декларация соответствует, то вызывается неправильно - Values и Errors должны вернуть указатель на SafeArray, передавать при вызове в них ничего не надо.


 
AbrosimovA   (2006-01-11 13:52) [4]

Скорее всего нужно так:

function ReadOPCItemProperties(Group: IUnknown; ItemServerHandle: OPCHANDLE;
         var ItemTimeStamp: TFileTime; var ItemValue: OleVariant;
         var ItemQuality: Word): HResult;
var
 SyncIOIf: IOPCSyncIO;
 Errors: PResultList;
 ItemValues: POPCITEMSTATEARRAY;
begin
Result := E_FAIL;
Errors:=nil;
ItemValues:=nil;
if Group = nil then Exit;
try
 SyncIOIf := Group as IOPCSyncIO;
except
 SyncIOIf := nil;
 Exit;
end;
Result := SyncIOIf.Read(OPC_DS_CACHE, 1, @ItemServerHandle, ItemValues,
                           Errors);
if Succeeded(Result) then
begin
 Result := Errors[0];
 CoTaskMemFree(Errors);
 Errors:=nil;
 ItemValue := ItemValues[0].vDataValue;
 ItemQuality := ItemValues[0].wQuality;
 ItemTimeStamp := ItemValues[0].ftTimeStamp;
 VariantClear(ItemValues[0].vDataValue);
 CoTaskMemFree(ItemValues);
 ItemValues:=nil;
end;
end;


 
alex_s   (2006-01-11 15:02) [5]


> И откуда взята декларация SyncRead?


Путем импорта библиотеки типов (OCSDAAuto.dll) получен модуль OPCAutomation_TLB.pas.
Вот выдержки описание:

unit OPCAutomation_TLB;
...
// *********************************************************************//
// Interface: IOPCGroup
// Flags:    (4416) Dual OleAutomation Dispatchable
// GUID:      {49C687D9-2A18-11D3-A5BC-0050043EC1B2}
// *********************************************************************//
 IOPCGroup = interface(IDispatch)
   ["{49C687D9-2A18-11D3-A5BC-0050043EC1B2}"]
...
   procedure SyncRead(Source: Smallint; NumItems: Integer;
       var ServerHandles: PSafeArray; out Values: PSafeArray;
       out Errors: PSafeArray; out Qualities: OleVariant;
       out TimeStamps: OleVariant); safecall;
...
   end;

// *********************************************************************//
// DispIntf:  IOPCGroupDisp
// Flags:    (4416) Dual OleAutomation Dispatchable
// GUID:      {49C687D9-2A18-11D3-A5BC-0050043EC1B2}
// *********************************************************************//
 IOPCGroupDisp = dispinterface
   ["{49C687D9-2A18-11D3-A5BC-0050043EC1B2}"]
...
   procedure SyncRead(Source: Smallint; NumItems: Integer;
                     var ServerHandles: {??PSafeArray}OleVariant;
                     out Values: {??PSafeArray}OleVariant;
                     out Errors: {??PSafeArray}OleVariant;
                     out Qualities: OleVariant;
                     out TimeStamps: OleVariant); dispid 1610743828;
...  
 end;

// *********************************************************************//
// OLE Server Proxy class declaration
// Server Object    : TOPCGroup
// Help String      : OPC Automation Group
// Default Interface: IOPCGroup
// Def. Intf. DISP? : No
// Event  Interface: DIOPCGroupEvent
// TypeFlags        : (2) CanCreate
// *********************************************************************//
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
 TOPCGroupProperties= class;
{$ENDIF}
 TOPCGroup = class(TOleServer)
 private
...
 protected
...
 public
   constructor Create(AOwner: TComponent); override;
   destructor  Destroy; override;
...
   procedure SyncRead(Source: Smallint; NumItems: Integer;
                     var ServerHandles: PSafeArray;
                     out Values: PSafeArray;
                     out Errors: PSafeArray); overload;
   procedure SyncRead(Source: Smallint; NumItems: Integer;
                     var ServerHandles: PSafeArray;
                     out Values: PSafeArray;
                     out Errors:PSafeArray;
                     out Qualities: OleVariant); overload;
   procedure SyncRead(Source: Smallint; NumItems: Integer;
                     var ServerHandles: PSafeArray;
                     out Values: PSafeArray;
                     out Errors: PSafeArray;
                     out Qualities: OleVariant;
                     out TimeStamps: OleVariant); overload;
 published
...
 end;

procedure TOPCGroup.SyncRead(Source: Smallint; NumItems: Integer; var ServerHandles: PSafeArray;
                           out Values: PSafeArray; out Errors: PSafeArray);
begin
 DefaultInterface.SyncRead(Source, NumItems, ServerHandles, Values, Errors, EmptyParam, EmptyParam);
end;

procedure TOPCGroup.SyncRead(Source: Smallint; NumItems: Integer; var ServerHandles: PSafeArray;
                           out Values: PSafeArray; out Errors: PSafeArray;
                           out Qualities: OleVariant);
begin
 DefaultInterface.SyncRead(Source, NumItems, ServerHandles, Values, Errors, Qualities, EmptyParam);
end;

procedure TOPCGroup.SyncRead(Source: Smallint; NumItems: Integer; var ServerHandles: PSafeArray;
                           out Values: PSafeArray; out Errors: PSafeArray;
                           out Qualities: OleVariant; out TimeStamps: OleVariant);
begin
 DefaultInterface.SyncRead(Source, NumItems, ServerHandles, Values, Errors, Qualities, TimeStamps);
end;


> А если декларация соответствует, то вызывается неправильно
> - Values и Errors должны вернуть указатель на SafeArray,
>  передавать при вызове в них ничего не надо.


A2:=VarArrayCreate([0,1],varVariant);
A3:=VarArrayCreate([0,1],varVariant);
Val:=PSafeArray(TVarData(A2).VArray);
Err:=PSafeArray(TVarData(A3).VArray);

это лишнее. Вы правы.

Ошибка скорее всего в передаче ServerHandles.
Может я его не так передаю.

Значение одной переменной читается:

procedure TForm1.Button2Click(Sender: TObject);
var v,q,ts:oleVariant;
begin
 My_OPCItem:=My_OPCGroup.OPCItems.Item(Memo1.ItemIndex+1);
 My_OPCItem.Read(2,v,q,ts);
 Edit16.Text:=IntToStr(v);
 Edit17.Text:=IntToStr(q);
 Edit18.Text:=TimeToStr(ts);
end;

Read(Source:integer; out Value:oleVariant; out Qualities:oleVariant;
       out TimeStamps:oleVariant);


> AbrosimovA   (11.01.06 13:52) [4]

Предлагаете использовать OPC Data Access Custom Interface Specification?
Но через OPC Data Access Automation Specification тоже ведь должно работать?


 
Набережных С. ©   (2006-01-11 18:30) [6]


> alex_s   (11.01.06 15:02) [5]

Я бы предпочел увидеть описание интерфейса на IDL, но да ладно, вряд-ли здесь есть ошибка.

> Ошибка скорее всего в передаче ServerHandles.

Скорее всего. Думаю, нужно разбираться с типом и, возможно, количеством элементов массива, которые ожидает метод. И, конечно, учитывать наличие модификатора VAR при этом параметре.


 
AbrosimovA   (2006-01-12 11:03) [7]

Вообще-то в opcda20_auto.doc процедура описана следующим образом:

SyncRead(Source As Integer, NumItems As Long, ServerHandles() As Long, ByRef Values() As Variant,  ByRef Errors() As Long, Optional ByRef Qualities As Variant, Optional ByRef TimeStamps As Variant)



Страницы: 1 вся ветка

Текущий архив: 2007.09.23;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.024 c
4-1175167368
MikeZ
2007-03-29 15:22
2007.09.23
Нажатие на элемент меню чужого приложения


2-1188375062
Int23
2007-08-29 12:11
2007.09.23
Можно ли не модальную форму сделать модельной?


2-1188228228
Антон Шестаков
2007-08-27 19:23
2007.09.23
сортировка при заполнении


15-1187936522
leonidus
2007-08-24 10:22
2007.09.23
Глюки при отображении формы в D6


15-1188226793
неискушенный
2007-08-27 18:59
2007.09.23
Просто интересно