|  | 
 
 | 
| 
 | |||||||
| Регистрация | << Правила форума >> | 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, 04.12.2024 в 09:46. | 
| 
			 
			#10  
			
			
			
			
		 | |||
| 
 | |||
|   Ну делай такой объект. Только помни, что в интерфейсах нет property, оно реализуется как 2 метода - getX и setX, если правильно помню.  https://docwiki.embarcadero.com/RADS...e_Type_Library |