|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Передача массива в собственную ComDll
Здравстуйте!Дело в том что нельзя выбрать параметр как массив,как и создать свой тип данных например TArrayString. Но пришла идея передать массив как OleObject
Код:
obj:=CreateOleObject("System.Collections.ArrayList") в него obj.Clear ; obj.Add(<строка>) И передаем в функцию : MyArrayFunc(obj:OleVariant):Variant; И также можем из функции Dll передать данные обратно в виде OleObject Последний раз редактировалось Admin, 28.11.2024 в 11:49. |
#2
|
|||
|
|||
вот что нагенерил ИИ:
Код:
type IMyComInterface = interface(IDispatch) ['{00000000-0000-0000-0000-000000000000}'] procedure ProcessArray(Values: OleVariant); safecall; end; Код:
procedure TMyComObject.ProcessArray(Values: OleVariant); var i: Integer; begin if VarIsArray(Values) then begin for i := VarArrayLowBound(Values, 1) to VarArrayHighBound(Values, 1) do begin // Process each element in the array ShowMessage(IntToStr(Values[i])); end; end; end; Вызов: Код:
var ComObj: IMyComInterface; Values: OleVariant; begin ComObj := CreateComObject(CLASS_MyComObject) as IMyComInterface; Values := VarArrayCreate([0, 2], varInteger); Values[0] := 10; Values[1] := 20; Values[2] := 30; ComObj.ProcessArray(Values); end; Тут передача интов в примере, поменять на varString, а исходный массив - простой динамический массив, только надо посмортеть, если не ошибаюсь, то лучше использовать Array Of WideString Последний раз редактировалось lmikle, 29.11.2024 в 04:31. |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
infopol (29.11.2024)
|
#3
|
|||
|
|||
Дело в том,что я делаю собственные ComDll для бухпрограммы...
Приветствую! Я работаю с программой "Инфо-Предприятие",не все там есть,но при небольшом умении программирования в Delphi( CBuilder я не знаю) можно дополнить и причем значительно функционал.
Вот и придумал использовать данные Объект как параметр. Ну если можно создать свой OleObject например ArreyObj с методами Add,Count,Item и т.д...было бы неплохо получить исходный код такого объекта и внедрить ее в свою библу. |
#4
|
|||
|
|||
А тебе и не надо создавать именно COM-объект для этого.
Можешь создать простой класс с твоими методами Add/Count/Items и т.д. И еще один метод, например, toOleArray, который и сформирует тебе OleVariant с упакованным внутрь массивом. Более того, если верися Дельфи не очень старая, то можно сделать шаблонный класс. Тогда можно будет упаковывать в такие массивы любые данные. Кстати, таким образом можно упаковывать и COM-объекты для передачи. |
#5
|
|||
|
|||
Сделал такой пример
Цитата:
Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,ComObj, OleConst,OleCtrls,ShlObj, ComServ,Types, Dialogs, StdCtrls; type IMyComInterface = interface ['{00000000-0000-0000-C000-000000000000}']//{00CA209B-5FB2-4EDA-952C-4C286F59EF9B}'] // function GetNumber : Integer; end; TMyComObject = class (TInterfacedObject,IMyComInterface) private procedure ProcessArray(Values: OleVariant); public end; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation //const //CLASS_MyComObject: TGUID = '{00000000-0000-0000-C000-000000000000}'; {$R *.dfm} procedure TMyComObject.ProcessArray(Values: OleVariant); var i: Integer; begin form1.Memo1.Clear; form1.Memo1.Lines.Add('Òåñò ïðîöåäóðû ProcessArray(Values)'); if VarIsArray(Values) then begin form1.Memo1.Lines.Add('Ðàçìåð '+IntToStr(VarArrayHighBound(Values, 1)+1 )); for i := VarArrayLowBound(Values, 1) to VarArrayHighBound(Values, 1) do begin // Process each element in the array form1.Memo1.Lines.Add(IntToStr(Values[i])); // ShowMessage(IntToStr(Values[i])); end; end; end; procedure TForm1.Button1Click(Sender: TObject); var ComObj: TMyComObject;//IMyComInterface; Values: OleVariant; begin ComObj:=TMyComObject.Create(); //ComObj := //CreateComObject(CLASS_MyComObject) as IMyComInterface; Values := VarArrayCreate([0, 4], varInteger); Values[0] := 10; Values[1] := 20; Values[2] := 30; Values[3] := 40; Values[4] := 50; ComObj.ProcessArray(Values); ComObj.Destroy; end; initialization end. Последний раз редактировалось infopol, 30.11.2024 в 10:25. |
#6
|
|||
|
|||
Непонятно что конкретно тебе надо сделать. Точнее в чем проблема.
Вот более полный пример: Форма: Код:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Unit2, Unit3, Vcl.StdCtrls; type TForm1 = class(TForm) btAddStr1: TButton; btAddStr2: TButton; btAddStr3: TButton; btCall: TButton; procedure btAddStr1Click(Sender: TObject); procedure btAddStr2Click(Sender: TObject); procedure btAddStr3Click(Sender: TObject); procedure btCallClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } Buf : TParamsColleator; procedure AddStrToBuf(S : String); public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.AddStrToBuf(S: String); begin if Not Assigned(Buf) then Buf := TParamsColleator.Create; Buf.Add(S); end; procedure TForm1.btAddStr1Click(Sender: TObject); begin AddStrToBuf('Str1'); end; procedure TForm1.btAddStr2Click(Sender: TObject); begin AddStrToBuf('Str2'); end; procedure TForm1.btAddStr3Click(Sender: TObject); begin AddStrToBuf('Str3'); end; procedure TForm1.btCallClick(Sender: TObject); var Intf : IComDemoInterface; params : OleVariant; begin If Not Assigned(Buf) Then raise Exception.Create('Buf is empty. Add values first.'); Intf := TComDemoImpl.Create; Try params := Buf.GetParamsArray; Intf.ProcessArray(params); Finally Intf := Nil; End; end; procedure TForm1.FormCreate(Sender: TObject); begin Buf := Nil; end; procedure TForm1.FormDestroy(Sender: TObject); begin If Assigned(Buf) Then FreeAndNil(Buf); end; end. Интерфейс с имплементацией: Код:
unit Unit2; interface type IComDemoInterface = interface(IUnknown) ['{00000000-0000-ABCD-0000-000000000001}'] procedure ProcessArray(arr: OleVariant); safecall; end; TComDemoImpl = class(TInterfacedObject, IComDemoInterface) procedure ProcessArray(arr: OleVariant); safecall; end; implementation uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants; { TComDemoImpl } procedure TComDemoImpl.ProcessArray(arr: OleVariant); var I : Integer; S : String; begin If Not VarIsArray(arr) Then MessageBox(0,PChar('<no data>'),PChar('Received call, but param is not array:'),0) Else Begin S := ''; For I := VarArrayLowBound(arr,1) To VarArrayHighBound(arr,1) Do If VarIsStr(arr[i]) Then S := S + IntToStr(I) + ' : ' + arr[i] + #10#13 Else S:= S + IntToStr(I) + ' : <not string>' + #10#13; MessageBox(0,PChar(S),PChar('Received call:'),0); End; end; end. Аккумулятор для параметров (самый простейший, просто унаследовался от TStringList и добаил свою функцию): Код:
unit Unit3; interface uses System.SysUtils, System.Variants, System.Classes; type TParamsColleator=class(TStringList) public function GetParamsArray : OleVariant; end; implementation { TParamsColleator } function TParamsColleator.GetParamsArray: OleVariant; var I : Integer; begin Result := VarArrayCreate([0,Count-1],varOleStr); For I := 0 To Count-1 Do Result[i] := Strings[i]; end; end. |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
infopol (02.12.2024)
|
#7
|
|||
|
|||
Описание задачи
Спасибо за ответ.Вот описание задачи по созданию ComDLL
1. Создать Com Dll 2. OleObject ArrayCom -OleVariant,можно TypeArray - тип данных в массиве. 3. Свойства Count -количество элементов в массиве 4. Методы Add - добавление в массив,Del (<N>) удаление элемента массива,Sort - сортировка массива,Revers- реверсирование,Clear - Очистка массива, Items[<N>] - получение значения массива Variant,OnArray - Array of variant. Код:
Arr:=CreateOleObject('ArrayCom') Arr.Clear; Arr.Add('Привет') Arr.Add('это библиотека ') Arr.Add('ArrayCom.Dll') //или {Arr.Add(100) Arr.Add(245) Arr.Add(1009) } for i=0 to Arr.Count do ShowMessage(VarToString(Arr.Items[i])) Последний раз редактировалось infopol, 02.12.2024 в 11:06. |
#8
|
|||
|
|||
Ой, чёт мне кажется, что это какое-то учебное задание.
А мы помним, что COM - это stateless модель? Это так, на всякий случай. По теме. Тогда тебе надо создавать ActiveX Library, внутри нее COM object и уже там, в библиотеке типов создавать свойства и методы, а потом реализовывать это в Co-классе. Просто по пути не забываем, что нам надо использовать COM-safe типы данных (например, обычная паскалевская строка, которая String, не является таким типом). Тут я бы посоветовал найти видел по тому как работать с редактором библиотеки типов в Дельфи. Это именно тот случай, когда лучше один раз увидеть... Ну а внутренняя реализация всех этих методов довольно стандартна. |
#9
|
|||
|
|||
Вот так должен использоваться объект из DLL
Цитата:
Должно быть по примеру Код:
ЕСЛИ ЕСТЬ_ОБЪЕКТ("System.Collections.ArrayList") ТО arr=СОЗДАТЬ_ОБЪЕКТ!("System.Collections.ArrayList") arr.Clear arr.Add("Привет") arr.Add("Всем") arr.Add("от меня") //arr.Reverse() //arr.Sort() // arr.Remove("Всем") // arr.RemoveAt(2) //N= arr.Count пар!""="" ОБНУЛИТЬ(пар) ЦИКЛ ДЛЯ(а=0,arr.Count-1) //ОТЛАДКА(arr.Item[а]) пар!а = arr.Item[а] КОНЕЦ_ЦИКЛА КОНЕЦ_ЕСЛИ переменная добавляемая в массив объекта ArrayCom может быть Число,Строка,Дата,Логика,Время. П.П. Заранее благодарен за помощь. Последний раз редактировалось infopol, Сегодня в 09:46. |