COM问题, 这样的问题你们难道没遇见过吗? 没找到有这样的资料! (300分)

  • 主题发起人 主题发起人 kkyy
  • 开始时间 开始时间
K

kkyy

Unregistered / Unconfirmed
GUEST, unregistred user!
我在一个类型库中定义了两个Automation;
例如, 一个IA, A; 一个IB, B, 于是自动产生了两个类: TAImpl和TBImpl
简略定义如下
class ATL_NO_VTABLE TAImpl:
...
{
private:
B* FB; //有Pbulic属性B可以Get
public:
TAImpl()
{ HRESULT hr; //请注意下面这句!
hr = CoCreateInstance(CLSID_B, NULL, CLSCTX_INPROC_SERVER,
IID_IB, (void **)&FB);
if ( SUCCEEDED ( hr ) ){
FB->A = this;
}
}
~TAImpl()
{
if( FB != NULL )FB->Release();

}
.........略
}

还有一个:
class ATL_NO_VTABLE TBImpl:
...
{
private:
A* FA;
public:
TBImpl()
{
}
.........略
}

我的目的很明显, 就是在A的实例创建时, 也创建一个B的实例,但是有一个问题,
Q:在同一个项目内, 创建B也只能用CoCreateInstance吗? 这好象太浪费资源了吧?
如果我要创建几百个几千个B, 这样行吗??
 
请大家说一说啊,
 
以下只是讨论。
问题再扩大一点,可能看得更清楚。这就是 COM 和类厂。COM 不是由应用程序直接创建对象
的,所有 COM 对象都由系统创建和管理,而创建它的工作是由工厂完成的。COM 工厂有一个
同质性,就是不同的 COM 对象的类厂,可以通过一个原始的工厂表达,所有具体的类工厂做
的都是一样的工作,也就是说,在应用程序中,只建立一个类工厂的实例,而不论你建立多少
个 COM 对象。每个 COM 对象需要的工厂,都只是这个类厂清单里的一个,实际工作都由同一
个工厂完成。因此,你只管调用 CoCreateInstance ,除了 COM 对象本身,它不会再给你另
外的工厂了。呵呵,批量生产的。
 
小雨哥说的有道理, 呵呵, 但这样我操作A里面的B, 只能通过外部属性或方法了, 所以考虑是否有效率问题,
还有, 我声明一个BSTR类型"可读写"属性, 刷新之后, 产生如下代码,
__property BSTR FileName = {read = get_FileName}; //没有write = set_FileName
当类型库中只有一个接口对象时, 并没有什么关系, 因为实际设置和读取是没问题的,
但当有两个接口对象的时候, 就有问题了,
以例如A->B->FileName = bstr_test;的语句设置时, 编译器竟然说只读属性不可设置!
当然, 只要修改__property 这个语句, 添加write是可以的, 但这样刷新一下又没了,
以上是C6的, 我试过如果用C3做, __property 语句里面是有write = ...的, 是不是C6退步了? 呵呵,
 
我见分眼开!
 
比如ADO库中, 当创建返回一个记录集的时候, 要生成很多FIELD实例, 我想它会不会是用别的办法的? 呵呵.
最好哪个高手能给个一个类型库中多个对象相互操作的例程, BCB或DELPHI的都可以, 如果VC的, 请小一点, 呵呵,
 
我做了个实验,,是在D6里的。。

工程文件:
// Project1.dpr
//
program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Project1_TLB in 'Project1_TLB.pas',
Unit2 in 'Unit2.pas' {Test: CoClass},
Unit3 in 'Unit3.pas' {A: CoClass};

{$R *.TLB}

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
////////////////////////////////////////////////////////////
// Unit2.pas 测试用的 Automation Test 单元文件, 相当于你的 B;
/////////////////////////////////////////////////////////////
unit Unit2;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, Project1_TLB, StdVcl;

type
TTest = class(TAutoObject, ITest)
private
FName : Widestring;
protected
function Get_Name: WideString; safecall;
procedure Set_Name(const Value: WideString); safecall;
{ Protected declarations }
end;

implementation

uses ComServ;

function TTest.Get_Name: WideString;
begin
Result := FName;
end;

procedure TTest.Set_Name(const Value: WideString);
begin
FName := Value;
end;

initialization
TAutoObjectFactory.Create(ComServer, TTest, Class_Test,
ciMultiInstance, tmApartment);
end.
////////////////////////////////////////////////
// Unit3.pas 另一个测试 Automation A
///////////////////////////////////////////////
unit Unit3;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, Project1_TLB, StdVcl, Unit2;

type
TA = class(TAutoObject, IA)
private
FName: WideString;
FTest : ITest;

protected
function Get_TestName: ITest; safecall;
{ Protected declarations }
end;

implementation

uses ComServ;

function TA.Get_TestName: ITest;
begin
if FTest = nil then
FTest := CoTest.Create;
Result := FTest;
end;


initialization
TAutoObjectFactory.Create(ComServer, TA, Class_A,
ciMultiInstance, tmApartment);
end.

///////////////////////////////////////////////////
// Project1_TLB.pas
//////////////////////////////////////////////////

unit Project1_TLB;

// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //

// PASTLWTR : $Revision: 1.130 $
// File generated on 2003-4-29 9:50:55 from Type Library described below.

// ************************************************************************ //
// Type Lib: C:/Program Files/Borland/Delphi6/Projects/DFW/COM/Project1.tlb (1)
// LIBID: {C973560E-3E3E-4BD5-8B62-E467A32431D4}
// LCID: 0
// Helpfile:
// DepndLst:
// (1) v2.0 stdole, (C:/WINNT/System32/stdole2.tlb)
// (2) v4.0 StdVCL, (C:/WINNT/System32/stdvcl40.dll)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}

interface

uses ActiveX, Classes, Graphics, StdVCL, Variants, Windows;


// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
Project1MajorVersion = 1;
Project1MinorVersion = 0;

LIBID_Project1: TGUID = '{C973560E-3E3E-4BD5-8B62-E467A32431D4}';

IID_ITest: TGUID = '{9A3F2805-3406-48D8-98DC-31AF1B0753F9}';
CLASS_Test: TGUID = '{EBCF5E95-1D11-4FA1-8F27-9A6E7269E8BA}';
IID_IA: TGUID = '{DE631DDC-A798-4C43-A11A-7F5E655417CA}';
CLASS_A: TGUID = '{F22E6C6E-5209-4E08-89CA-61AAF7353951}';
type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
ITest = interface;
ITestDisp = dispinterface;
IA = interface;
IADisp = dispinterface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
Test = ITest;
A = IA;


// *********************************************************************//
// Interface: ITest
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {9A3F2805-3406-48D8-98DC-31AF1B0753F9}
// *********************************************************************//
ITest = interface(IDispatch)
['{9A3F2805-3406-48D8-98DC-31AF1B0753F9}']
function Get_Name: WideString; safecall;
procedure Set_Name(const Value: WideString); safecall;
property Name: WideString read Get_Name write Set_Name;
end;

// *********************************************************************//
// DispIntf: ITestDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {9A3F2805-3406-48D8-98DC-31AF1B0753F9}
// *********************************************************************//
ITestDisp = dispinterface
['{9A3F2805-3406-48D8-98DC-31AF1B0753F9}']
property Name: WideString dispid 1;
end;

// *********************************************************************//
// Interface: IA
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {DE631DDC-A798-4C43-A11A-7F5E655417CA}
// *********************************************************************//
IA = interface(IDispatch)
['{DE631DDC-A798-4C43-A11A-7F5E655417CA}']
function Get_TestName: ITest; safecall;
property TestName: ITest read Get_TestName;
end;

// *********************************************************************//
// DispIntf: IADisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {DE631DDC-A798-4C43-A11A-7F5E655417CA}
// *********************************************************************//
IADisp = dispinterface
['{DE631DDC-A798-4C43-A11A-7F5E655417CA}']
property TestName: ITest readonly dispid 2;
end;

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

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

implementation

uses ComObj;

class function CoTest.Create: ITest;
begin
Result := CreateComObject(CLASS_Test) as ITest;
end;

class function CoTest.CreateRemote(const MachineName: string): ITest;
begin
Result := CreateRemoteComObject(MachineName, CLASS_Test) as ITest;
end;

class function CoA.Create: IA;
begin
Result := CreateComObject(CLASS_A) as IA;
end;

class function CoA.CreateRemote(const MachineName: string): IA;
begin
Result := CreateRemoteComObject(MachineName, CLASS_A) as IA;
end;

end.



/////////////////////////////////////////////////////////
// 测试程序代码
//////////////////////////////////////////////////////

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;

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

var
Form1: TForm1;

implementation

uses
project1_TLB;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
tmp : IA;
begin
Tmp := CoA.Create;
tmp.TestName.Name := 'Test..'; // 在这儿写入属性,,

button1.Caption := Tmp.TestName.Name; //这里读取属性到 Button 的标签上,,

end;

end.
我的环境 Windows 2000 Server ,,D6
测试通过可以实现。。
 
to darnis:
多谢您的指点, 呵, 我用Delphi玩好象也是可以的,但是因为现有在部份代码是C++的,
所以我需要用BCB或VC做,我本想BCB稍简单一点, 哪料就是不大行, 呵呵,
 
你用的 BCB 6?
我前些天也安了的,,不过有些影响系统(系统不稳),,我就把她给
卸掉了,, :((

我不知道你在你的A里引用B时,是怎么用的?是用向导创建的还是人工创建的?
我在D6里是用向导创建的,而且在 A的 CoClass 的 Implements 页里点右键
加入了 IB,,
这不知道对你的结果有没有影响,,?
因为以前我遇到过一个例子,跟这个过程有点关系的。。
 
是手工加入的, 呵呵, 可能和D有些不同, 提示是不能实例化抽象对象,
 
改用VC7搞定,BCB好象玩COM还是不大好玩呀。
 
后退
顶部