-
_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
-
> Ну а примера ни у кого нет, как ее использовать? В хелпе
> что то не густо про 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 в сервере и контроллере отличаются. -
> 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?