Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Corba";
Текущий архив: 2007.09.23;
Скачать: [xml.tar.bz2];

Вниз

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 вся ветка

Форум: "Corba";
Текущий архив: 2007.09.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.043 c
15-1188204481
zdm77
2007-08-27 12:48
2007.09.23
Локальные админы


2-1188379446
Женя_кэт
2007-08-29 13:24
2007.09.23
Запись RTF файла в БД


3-1179649816
PaintenZero
2007-05-20 12:30
2007.09.23
Создание XLS БД


2-1188505371
azl
2007-08-31 00:22
2007.09.23
Выравнивание текста в отдельной ячейке StringGrid


2-1188280980
Alex8
2007-08-28 10:03
2007.09.23
SELECT





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский