Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

OPC + Delphi + SafeArray =???


a_k_v ©   (2002-01-22 08:36:00) 

я импортировал библиотеку типов из OPC сервера.
простые иетоды из библиотеки не требующие
параметров, или с параметрами WideString, Integer и т. д.
вызываются без проблем, а методы требующие в качестве параметров
PSafeArray выдают ошибку "The parameter is incorrect"

Отсюда вопрос: возможно ли в принципе из Delphi через OLE и OPC
передавать в качестве параметров массивы SafeArray, если да то как.

P.S.: В VB в качестве этих параметров для OPC сервера передаются динамические массивы:
Dim A() as String;
Dim B() as Integer;
и т.д.


Yuri Dubrov   (2002-03-02 00:40:00) [1]

Вот как я получалсписок источников данных ODBС с помощью функции GetDataSourceList (из библиотеки ODBCTool.dll). Эта функция создает внутри себя SafeArray и возвращает ссылку на него. Ссылка - типа PSafeArray. Как ею воспользоваться?

Надо создать переменную типа Variant. В моем примере это переменная a. На самом деле, Variant внутри является структурой типа TVarData. В поля этой структуры записываем:

- Тип вариантной переменной:
TVarData(a).VType := varOleStr + varArray;

- Полученную ссылку на массив:
TVarData(a).VArray := PVarArray(plst);

Дальше можно спокойно работать с вариантной переменной.

Вот работающий пример:



uses
ODBCTool_TLB, ActiveX

{...}

procedure TForm1.ODBCDSNComboBoxDropDown(Sender: TObject);
var
ds: DSN;
plst: PSafeArray;
a: Variant;
i: integer;
t: integer;
begin
ODBCDSNComboBox.Items.Clear;

{получим список DSN}
ds := CoDsn.Create;
ds.GetDataSourceList(plst);

{"обернем" его в вариантный массив}
TVarData(a).VArray := PVarArray(plst);
TVarData(a).VType := varOleStr + varArray;

{теперь используем}
for i:= VarArrayLowBound(a,1) to VarArrayHighBound(a,1) do
ODBCDSNComboBox.Items.Add(VarToStr(a[i]));

ds := nil;

end;


Digitman   (2002-01-23 12:08:00) [2]

посмотри пример реализации методов

TDataBlockInterpreter.WriteArray()
TDataBlockInterpreter.ReadArray()

в модуле SConnect.

эти методы задействуют механизмы передачи вариантных массивов по стандартным OLE-соглашениям в части маршаллинга интерфейсных вызовов с SafeArray-параметрами


a_k_v   (2002-01-23 05:36:00) [3]

to Digitman
>> создай переменную типа SafeArray, заполни массив,...
нет ли у вас примера реализации?


a_k_v   (2002-01-23 05:33:00) [4]

to handra
Вызов с VarArrayRef не компилируется ругается, что параметр
не тот.

вот описание функции из библиотеки типов:
procedure AddItems(NumItems: Integer;
var ItemIDs: SafeArray;
var ClientHandles: PSafeArray;
out ServerHandles: PSafeArray;
out Errors: PSafeArray; RequestedDataTypes: OleVariant;
AccessPaths: OleVariant); safecall;

var
NumItems: Integer;
ItemsIDs, ClientHandles,..., : Variant;
begin
...
// Вот так создаю массивы
ItemsIDs := VarArrayCreate([1,10]), varVariant);
ClientHandles := VarArrayCreate([1,10]), varVariant);
// Заполняю как всегда
ItemsIDs[i] := ...
// а вот так пытаюсь вызвать функцию

ItemCollection.AddItems(NumItems,
PSafeArray(TVarData(ItemsIds).Varray) ,
PSafeArray(TVarData(ClientHandles).Varray),
PSafeArray(TVarData(ServerHandles).Varray),
PSafeArray(TVarData(Errors).Varray),
ReqDataTypes, sAccPath);
и на этапе выполнения получаю "The parameter is incorrect"
то же и при попытке задать вместо varVariant конкретные типы.
???





...


handra   (2002-01-22 11:01:00) [5]

пример:

ByteData: Variant;
ByteArr: PByteArr;
P: Pointer;
n: Integer;

//вызов функции с сылкой на SafeArray - ByteData
IGeoMap.LoadObjectData(0,0,VarArrayRef(ByteData));
//определяем размер в байтах
n := VarArrayHighBound(ByteData,1)-VarArrayLowBound(ByteData,1)+1;
//Выделяем память для данных и копируем их
P := VarArrayLock(ByteData);
GetMem(ByteArr,n);
Move(P^,ByteArr^,n);
VarArrayUnLock(ByteData);
//Освобождаем ресурс
ByteData := NULL;


Все это уже год стабильно работает.


Digitman   (2002-01-22 11:00:00) [6]

создай переменную типа SafeArray, заполни массив, контролируемый этой переменной, значениями и передай указатель на переменную (приведенный к типу PSafeArray) в кач-ве параметра интефейсного вызова


Наверх

Титульная страница Поиск, карта сайта Написать письмо