Конференция "Corba" » Передача ссылки на созданный объект в другой процесс (маршалинг) [Delphi, Windows]
 
  • _Z_ (01.04.08 08:53) [0]
    Ищется пример передачи ссылки на созданный объект (интерфейс) в другой процесс. Что то сам не осилил пока.
  • Сергей М. © (01.04.08 09:36) [1]

    > Ищется пример


    sconnect.pas
  • _Z_ (01.04.08 11:58) [2]
    Что то я там не нашел передачу в другой процесс. Хотелось бы примерчик двух приложений. В одном создали объект. В другом получили на него ссылку и вызвали метод.
  • clickmaker © (01.04.08 12:11) [3]

    > В одном создали объект. В другом получили на него ссылку
    > и вызвали метод

    IPC? RPC? DCOM?
    sconnect из той же оперы
  • _Z_ (01.04.08 12:23) [4]
    Я просто только недавно за КОМ принялся. Я так понимаю sconnect - это бибиотека, которая делает то, что мне надо? Ну а примера ни у кого нет, как ее использовать? В хелпе что то не густо про sconnect
  • tesseract © (01.04.08 12:35) [5]

    > Ну а примера ни у кого нет, как ее использовать? В хелпе
    > что то не густо про sconnect


    Вариантов много, в том числе и передача процессу ссылки на экземляр самого себя, или через IStream.
  • Сергей М. © (01.04.08 12:43) [6]

    > _Z_   (01.04.08 11:58) [2]
    >
    > Что то я там не нашел передачу в другой процесс


    Ты же про маршаллинг спросил ?
    Вот SConnect как раз и иллюстрирует "потроха" этого страшного слова)
  • _Z_ (01.04.08 14:51) [7]

    > в том числе и передача процессу ссылки на экземляр самого
    > себя


    Вот эта передача ссылки меня и интересует. Может кто нибудь набросает примерчик передачи (любым методом)?

    Просто в моей книге по COM есть только пример внутрипроцессной передачи, а вот такой нет.
  • _Z_ (01.04.08 15:01) [8]
    Вот допустим есть такой код:

    type

     ITest=Interface
       ['{72209886-43D9-40D2-A2DE-C86A96D1EDC5}']
       procedure TestProc(s:string);
     End;

     TTest=class (TInterfacedObject, ITest)
       procedure TestProc(s:string);
     End;

     TForm1 = class(TForm)
       Button1: TButton;
       procedure FormCreate(Sender: TObject);
       procedure Button1Click(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;
    //--------------
    procedure TTest.TestProc(s: string);
    begin
        ShowMessage(s);
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
        ComObj.TestProc('Test from ComServer');
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
        ComObj:=TTest.Create;
    end;



    Все понятно, когда из одного процесса использую.

    А вот теперь я хочу вызывать методы объекта ComObj (именно того экземпляра, который создался вместе с формой1). Как мне из приложения 2 получить ссылку на ComObj?

    Т.е. создаю еще одно приложение:


    type
    ITest=Interface
       ['{72209886-43D9-40D2-A2DE-C86A96D1EDC5}']
       procedure TestProc(s:string);
     End;

     TForm1 = class(TForm)
       Button1: TButton;
       procedure Button1Click(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;
     ComObj:ITest;

    implementation

    {$R *.dfm}

    procedure TForm1.Button1Click(Sender: TObject);
    begin
       //нужно получить ссылку на объект
       //ComObj:=????
       ComObj.TestProc('!!!');
    end;

    Вот как мне получить ссылку на ComObj, который я создал в приложении1?

  • Сергей М. © (01.04.08 15:35) [9]

    > как мне получить ссылку на ComObj, который я создал в приложении1


    При такой реализации - никак.

    Интерпроцессным взаимодействием на базе COM/DCOM заведует ОС, а твои приложения никоим образом не известили ОС о своих намерениях.
  • _Z_ (01.04.08 15:39) [10]

    > При такой реализации - никак.
    >
    > Интерпроцессным взаимодействием на базе COM/DCOM заведует
    > ОС, а твои приложения никоим образом не известили ОС о своих
    > намерениях.

    Ок, я догадывался, что я тут чего то не допонял. Может ли кто то ткнуть носом, как доделать реализацию сервера, чтобы я мог решить свою задачу? Может где то в инете статья есть или готовый пример?
  • Сергей М. © (01.04.08 15:56) [11]

    > как доделать реализацию сервера


    Проще будет ее не доделать, а переделать с нуля, танцуя от

    File -> New... -> ActiveX -> COM Object

    Статей в Тырнете на эту тему воз и тележка, в т.ч. и с примерами.
  • _Z_ (01.04.08 16:13) [12]

    > File -> New... -> ActiveX -> COM Object
    >
    > Статей в Тырнете на эту тему воз и тележка, в т.ч. и с примерами.
    >


    Вот я пока не нашел примеров, хотел здесь и спросить. Где их лучше поискать. Пока что то никак.
  • Сергей М. © (01.04.08 16:24) [13]

    > Где их лучше поискать


    Например, в книге Эрика Хармона "Разработка СОМ-приложений в среде Делфи"
  • _Z_ (01.04.08 16:55) [14]

    > Например, в книге Эрика Хармона "Разработка СОМ-приложений
    > в среде Делфи"

    Книга то и у меня есть (Делфи 6 и технология COM). Но в моей нету того, что я ищу. Но да ладно. Для начала хотя бы просто делаю создание объекта в области памяти сервера из клиента по этой книге (кстати вот точно из нее есть и в инете отрывок: http://www.interface.ru/fset.asp?Url=/borland/decom_1.htm):

    Сервер сделал через мастер и как по инструкции (включая библиотеку типов). Сам сервер внутри себя нормально создает объект и все работает. Теперь делаю другое приложение:
    var
     Form1: TForm1;
     ClntComObj:ITest2;

    implementation
    uses ActiveX, ComObj;

    {$R *.dfm}

    procedure TForm1.Button1Click(Sender: TObject);
    begin
       //нужно получить ссылку на объект
       //ComObj:=????
       ClntComObj:=CoTest2.Create;
       ClntComObj.TestProc('!!!');
    end;



    Кусок из кода, созданного мастером:


    // *********************************************************************//
    // Interface: ITest2
    // Flags:     (256) OleAutomation
    // GUID:      {FB2C1126-E459-4155-973D-89303FD0D547}
    // *********************************************************************//
     ITest2 = interface(IUnknown)
       ['{FB2C1126-E459-4155-973D-89303FD0D547}']
       function TestProc(const str: WideString): HResult; stdcall;
     end;

    // *********************************************************************//
    // The Class CoTest2 provides a Create and CreateRemote method to          
    // create instances of the default interface ITest2 exposed by              
    // the CoClass Test2. The functions are intended to be used by            
    // clients wishing to automate the CoClass objects exposed by the        
    // server of this typelibrary.                                            
    // *********************************************************************//
     CoTest2 = class
       class function Create: ITest2;
       class function CreateRemote(const MachineName: string): ITest2;
     end;

    implementation

    uses ComObj;

    class function CoTest2.Create: ITest2;
    begin
     Result := CreateComObject(CLASS_Test2) as ITest2;
    end;

    class function CoTest2.CreateRemote(const MachineName: string): ITest2;
    begin
     Result := CreateRemoteComObject(MachineName, CLASS_Test2) as ITest2;
    end;



    Сама реализация на сервере:

    type
     TTest2 = class(TTypedComObject, ITest2)
     public
       function TestProc(const str: WideString): HResult; stdcall;
       {Declare ITest2 methods here}
     end;

    implementation

    uses ComServ;

    function TTest2.TestProc(const str: WideString): HResult;
    begin
      ShowMessage('TestProc (ComSrv): '+str);
      Result:=S_OK;
    end;

    initialization
     TTypedComObjectFactory.Create(ComServer, TTest2, Class_Test2,
       ciMultiInstance, tmApartment);
    end.



    Теперь при вызове в клиенте:

    ClntComObj:=CoTest2.Create;

    при незапущенном сервер получаю ошибку Класс не зарегестрирован - все правильно.

    Запускаю ехе с сервером, запускаю клиента, жму кнопку, получаю исключение Interface not supported. Где косяк? В книжке типа все работает.
  • Сергей М. © (01.04.08 17:06) [15]

    > Где косяк?


    Первое что приходит в голову - декларации интерфейса ITest2 в части GUID в сервере и контроллере отличаются.
  • tesseract © (01.04.08 17:19) [16]

    >  ShowMessage('TestProc (ComSrv): '+str);


    Так из COM лучше не надо.


    > procedure TForm1.Button1Click(Sender: TObject);begin    //нужно
    > получить ссылку на объект    //ComObj:=????    ClntComObj:
    > =CoTest2.Create;    ClntComObj.TestProc('!!!');end;



    Например, следующий код будет успешно откомпилирован, но при выполнении вызовет ошибку «Interface not supported»:

    var
             Test: ITest;
    begin
             Test := TInterfacedObject.Create as ITest;
             Test.Beep;
    end;

    В то же время код

    var
             Test: ITest;
    begin
             Test := TTest.Create as ITest;
             Test.Beep;
    end;

    будет успешно компилироваться и выполняться.




    Читай КОРАН до конца. Из твоей же ссылки выдрано.
  • _Z_ (01.04.08 17:20) [17]

    > Первое что приходит в голову - декларации интерфейса ITest2
    > в части GUID в сервере и контроллере отличаются.

    Как они могут отличаться, когда используют общую библиотеку типов, где ITest2 и объявлен:


    unit COMSrv_TLB;

    // *********************************************************************//
    // Interface: ITest2
    // Flags:     (256) OleAutomation
    // GUID:      {FB2C1126-E459-4155-973D-89303FD0D547}
    // *********************************************************************//
     ITest2 = interface(IUnknown)
       ['{FB2C1126-E459-4155-973D-89303FD0D547}']
       function TestProc(const str: WideString): HResult; stdcall;
     end;

  • _Z_ (01.04.08 17:31) [18]

    > Читай КОРАН до конца. Из твоей же ссылки выдрано.

    Не понял. У нас есть библиотека типов для использования в клиенте (созданная мастером) - COMSrv_TLB. Все что у нас там есть - это
    CoTest2 = class
       class function Create: ITest2;
       class function CreateRemote(const MachineName: string): ITest2;
     end;


    и

    ITest2 = interface(IUnknown)
       ['{FB2C1126-E459-4155-973D-89303FD0D547}']
       function TestProc(const str: WideString): HResult; stdcall;
     end;



    Где я недопонял? TTest2 в этом модуле не значится. Да и вроде не нужен он, для этого у нас есть ITest2. В приведенном выше примере из книги показана проблема с вызовом из родительского класса, у меня он вообще один.
  • _Z_ (01.04.08 21:02) [19]
    И все таки не понятно, почему из самого сервера все работает, а из другого процесса Interface not supported?
 
Конференция "Corba" » Передача ссылки на созданный объект в другой процесс (маршалинг) [Delphi, Windows]
Есть новые Нет новых   [120347   +16][b:0][p:0.003]