| |
||||
|
Welcome to Sabbasoft |
||||
![]()
|
|
1) What's the difference between early binding and late binding ? |
|
Interfaces are the basic concept of COM. An interface is a
group of methods definition (read signature) conceptually related. In COM this group of methods
definition gets mapped at the binary level into a standard (among C++
compilers) layout (the so called VTable function pointer). When you bind to a "standard" interface you are early-binding to the interface. When you bind to a Dispinterface you are late-binding to the (Disp)interface. Of course, early-binding out-performs late-binding cause the last one
involves the overhaed of packing and unpacking datas back and forward to
fit them into the Invoke method. |
|
|
2) Createobject vs New. Dim as Object vs Dim as IMyInterface |
|
Consider this line of code: Dim x as Project1.Class1 Most of us use/used to think that we were declaring x as a
"Project1.Class1" class. Set x = CreateObject("Project1.Class1") 'OR One thing to stress: these 2 lines of codes are totally
equivalent regarding early or late binding.
There is a common misunderstanding among VB developers. They think that if
you use the New keyword you are early-binding and that if you use
CreateObject you are late-binding. Dim x as Object ' read Object as Dispatch The confusion arises from the fact that VB hides you from most of the
details of interface and classes definition. Dim x as New Project1.Class1 In this case [Project1.Class1] is a class identifier. You are asking VB to create the Project1.Class1 class, ask to the object its default interface and place it into the x variable. |
|
|
3) Why shouldn't I rely on VB runtime regarding objects release? |
| VB takes care to release the memory used by any
variable when it goes out of scope, nevertheless it's
better to Set explicitely your objects to Nothing for the following reasons: - It's a good programming techinique, this habitude could turn usefull if it happens you to program in C++. - It's better to release resources when you don't need them anymore, without waiting they go out of scope, this is expecially true if the objects keep DB connections open. - There are (yet ?) some ADO bugs that gives some problems (loss of information in the Err object) if you don't have set ADO objects explicitely to Nothing before raising an error. - Close Recordsets and Connections objects before setting them to Nothing, or connection pooling won't work correctly. |
|
|
|
| Although COM is "just" a binary layout definition, IDL has
become the "C-like" lingua franca of COM interface and class
definition. IDL is processed by MIDL.EXE to produce marshaling code
(necessary for non automation compliant interfaces), header definition
(for C++) and type library (for VB).
import "oaidl.idl";
In this sample the library decribes a COM Object named MYClass ([coclass]) that implements the IMYClass interface. In VB you map such "standard" COM definition declaring a Class module as Multiuse. PrivateNotCreatable classes are mapped to IDL tagging the [coclass] with the NonCreatable keyword. To get a pointer to such interfaces there must be another Multiuse in the same component (so that it knows how to create the COM object) that creates the PublicNotCreatable object, asks for one of its interface and passes it out of the component via a method parameter. When you mark a class as Public not Creatable VB do more then this: it removes the InprocServer entry in the registry under the class CLSID; in this way the COM runtime has no way to create the class, even from languages like C++ that ignores the coclass section of IDL. I just recently realized that the whole coclass section are just for documentation purpouses and for VB clients. Not creatable is an example, another example is the source tag to let VB know what is the default (actually the only VB can access) sink interface of the object (the default sink interface contains the events you define for the class in VB). Private classes does not appear in IDL at all.
|
|
|
|
|
In COM objects live in apartments. A third one will be in W2k: Neutral Threading
Apartment. In an STA there is just 1 thread running, it loops in an
hidden window message pump waiting for dispatching method calls to objects
living in the STA. In an MTA there is a pool of threads running, waiting to
serve incoming calls. In this case Syncronization is an issue. You have to deal
with OS syncronization primitives such Mutexes, Semaphore, Critical Sections,
etc ..
A COM object declares to the COM runtime its apartment requirements via the ThreadingModel key under the object's CLSID in the registry. These are the possible entries for this key: - no ThreadingModel entry : The object will be put
in the Main STA (a "special" STA, the first one created in the
process) |
|
6) How do I overcome VB's limits of the binary compatibility settings ? |
|
|
Among the different COM details that VB hides to the
programmers, one of the most problematic one is that it doesn't let you
take control on the interface GUIDs. Via the binary compatibility settings
VB tries to force you follow COM rules (as a fact breaking such rules with
the interface foward mechanism it silently implements when you add a
method to a class). In any case VB support in Interface definition and
maintenance is definetely lacking when you have to design and implement
large COM based systems.
Here i place to links where is illustrated (the same in both artcicles) a tecnique that lets overcome such limits. This approach may be scaring at first to VB programmers that are not that familiar with C language, cause you have to go a little deep into IDL, nevertheless, trust me, that, after the first little drop of you development speed, you will get much more robust and well designed applications. http://msdn.microsoft.com/library/techart/msdn_bldvbcom.htm One note: instead of using Oleviewer to reverse-engineer the Type library i suggest you to use the TypeLibrary Viewer from http://www.vivid-creations.com/ cause Oleviewer does not always generate IDL that can be immediately compiled by midl to generate the type library without a certain number of adjustments. I verified that this tool i suggest generates much more ready-to-compile IDL |
| 7) A few words about Byref / ByVal - Standard marshaling / Custom Marshaling By Value | |
|
There is quite a lot of misunderstanding in the VB-COM
"newbie" comunity, about what happens underneath when a COM
interfaces is passed as method parameters. As in most of the cases VB
programmers are hidden/protected about a lot of details on the COM
run-time, but you do have to know such details if you want to assemble
something that perform decently in a distributed environment. 1) Basic automation types (double,long,string) are passed by value if the method signature is declared byval. They are passed by reference if the method signature is declared byref. The behviour you experience is the same if the method call takes place in-Apartment or cross-Apartment. 2) COM Interfaces: The first thing to stress here is that in VB (or in any COM
aware language) you never get in touch with a Class (the client doesn't
have to know the class binary layout ! ), you get in touch with
interfaces. So when 'you' think to pass an "object" you are
actually passing an interface. The 'state' of underlying COM object that
is behind the interface is not copied (e.g. as a struct (type)
is). Now, coming to the point: to see this i show here the mapping between a VB method signature and the underlying IDL public sub test(byval a1 as IMyInterface1,byref a2 as IMyinterface2)
-> This means that, even if you pass an interface byval, you don't have
to be surprised that, on returning from the method call, one of its
properties have been changed. the latter is ----------------- sub a() sub b() ---------------------------------------------------------- You experience the same behaviour described above if you pass
Interfaces in-Apartment / or cross-Apartment (Cross Process / Cross
Host) if such interface are standard marshaled (Type-Library
marshaling). |
| 8) How do I implement proper Error Handling in VB ? | |
|
According to my personal experience, error handling code
does not deserve sufficient attention and standardization within VB developers
group. Most time each programmer is left free to implement his error handling
style (and most times the style is "no error handling at all"). I've heard someone saying: "we will implement error handling later", I came to know that, in this case, "later" meant a week-end at work for this guy. This was something I liked :), too many times I had to stare at an "ActiveX can't create object" .. asking myself where the hell this message came from. Implement proper error handling, according to me, means:
setting up an Error Handler while another Error Handler is active has no effect.
So .. stay tuned with the MS KB site if you go for the official way :) A basic Function implementation skeleton can be defined in the following way: Propagate via Com Exception Public Sub MyFunc()
Public Sub MyFunc(byref p_ErrorDescription) as
Long It's better to replace the return type from Long to an Enum of application defined error codes. They have to be published in the component Type-Library so that they are accessible by the client as well. This approach gives the following advantages:
The same approach is good when you use Com Exceptions as well. You don't get 1, but you still get 2 I've developed a little VB-Addin that generates
automatically the skeleton of "Return code" type Error handling. This is just a super-fast introduction to the subject.
You may want to read: Building a Better Mousetrap for COM+ (MTS) published at the VB2TheMax site to get deeper details. |
| 9) Can I store Interface pointers in the SPM ? | |
| No, you can't !! the SPM is unaware of Apartment marshaling issues.If you ask the SPM for an interface pointer while running in an aprtment that is different from the one where the interface pointer resides the SPM will blindly pass you the rough interface pointer without marshaling it, thus violating COM rules (and your app will randomly fail). Park the interface pointer in the GIT and park the GIT cookie in the SPM. |
| 10) Binary Compatibility of components | |
| When you decide to issue a new version of an MTS
component you should take care of its compatibility with the previous
version. There are three types of changes you could make: 1) You change only internal code of a component, keeping the interface that the component provides untouched. 2) You only add a member(s) (method, property, enum etc.) to the interface, but leave declaration of previously declared members quite the same. 3) You decided to revise the interface members and some of them are changed or even removed. Thus, if you're building a component in VB it's strongly recommended to set Version Compatibility of the project to Binary Compatibility mode. In this case VB will track the changes of the interface(s) and will notify you if you make changes of type (3), but not 2 ! To install a new version into MTS you should do the following: For changes of type (1) you can simply overwrite the older DLL with the newer one. The remote clients that had the client export registered need no intervention, but with both (2) and (3) types of changes you should completely reinstall the component (i.e. remove it from MTS and then install it back), you then need to re-export the package and have the remote clients run the client installation again (remove the old one before from Control Panel/Install remove applications). Don't forget to shut the component's package down to unlock components' DLLs. It's possible to shut a package down remotely and perform other administration operations "programmatically" (see MTS2.0 Admin Type Library) |
|
|
11) Object Pooling |
|
An excerpt from MTS documentation http://msdn.microsoft.com/library/psdk/mts20sp1/mtxpg04_8v6v.htm
: "Object pooling and recycling is not available in this release. MTS calls CanBePooled as described here, but no pooling takes place. This forward-compatibility encourages developers to use CanBePooled in their applications now in order to benefit from a future release without having to modify their applications later." This article refers to version 2.0 Service Pack1 of MTS and applies to Windows NT 4.0 system. Object pooling is a COM+ feature and is available under Windows 2000 platforms. It will be available for objects that declare a new threading model : the neutral threading apartment (nta) . Such objects don't have to have any thread affinity, and will have to enlist manually into transactions |
![]()
Comments, suggestions .. whatever .. drop me a line if you wish
| You are visitor number | Since 2001/01/01 |
|
Contact us at sabbadin@sabbasoft.com |