HOME  | DEMO  |  BUY-NOW  |  JAVA VERSION

   ComBridge (c) 1997-2006 Octatec ltd
   
ComBridge allows UNIX and Linux clients to access COM, DCOM and COM+ Automation objects residing on Windows (WIN32) systems. Support is included for retrieving and using ADO Recordsets. ComBridge can be embedded in CORBA wrappers facilitating CORBA/COM communication and UNIX/Windows connectivity. The system is implmeneted as a Client-Side library and a Server-Side WIN32 Service (or server program for WIN32 systems that don't support services.

Contents

Keywords: COM, DCOM, COM+, Active/X, Active/X Automation, OLE, OLE Automation, IDispatch, CORBA, UNIX, LINUX, Connectivity, Inter Operability.

Summary: ComBridge enables you to connect to WIN32 COM objects from UNIX or Linux systems via a simple client library and a WIN32 service.


Server Side Components

  • ComBridge Server (ComBridgeSrv.exe and ComBridgeService.exe)

  • In the full version, this is an NT service, but in the demo version it is a standalone EXE
  • Test Com Object (ComBdgTestObj.exe)

  • This object is used by the client-side test
  • The ADORSproxy object (ComBdgAdoPxy.dll)

  • This object provides ADO recordset functionality for ComBridge Clients
  • Interactive management and test utility (UseComBridgeSrvr.exe)

  • This program allows the server to be tested from other WIN32 systems, and provides some management functions and
  • This document in HTML format
No System DLLs are installed or changed on your system.

One directory will be added to your system, C:\Program Files\Octatec\ComBridge (by default), and all executables and documentation will be placed in there. Further information can be found in the Server Side Installation Guide

System Requirements

There are no special system requirements, you just need a WIN32 system with the TCP/IP protocol stack activated. ComBridge uses the standard sockets API for network access.

Registry Entries

The server uses several registry entries, more is said about these in the Server Configuration section

The Server Program

There are 2 versions of the server programs supplied with the system. One version has a User Interface (ComBridgeSrv.exe) that can be used on WIN32 systems that don't support services, i.e. Windows95; and one version that runs as an NT or Windows2000 service (ComBridgeService.exe). Note: the demo download contains only ComBridgeSrv.exe. NOTE: you do not need to run both versions of the server program.

The ComBridge service will be added to the system  by the installation program.  It will not, however, be started, and it will be configured for manual activation. To start it and/or to arrange to have the it started automatically at system boot, you should use the services icon from the control panel.

The Interactive version of the ComBridge server program must be started manually, it is not added to any program group. You must find it in the file system, using Windows Explorer, and double click it. The program is placed in C:\Program Files\Octatec\ComBridge by the installation procedure, however, you will have the opportunity to chose an alternative directory. ComBridgeSrv.exe has a minimal user interface - in order to receive incoming calls, you must take the Start option from the File menu, when the server is started, the client window will turn green. If the ComBridge Service is running, you should not try to start the ComBridge Server Program, and vice versa - only one ComBridge server can run on a system.
 

The ADORSproxy Object

This is a very simple automation object. It has just one method, GetRecordset() which allows a client to run a query on a database and obtain an IDispatch pointer to a recordset. This pointer can easily be used by attaching it to a RecordsetBridge object. See bellow for the  IDL definition of the object.

In order to use this object, you must already know an Ado Connection String and a Query String. If you don't know these, the owner of the database you wish to access will provide you with them. The Programing Guide below shows you how to use the ADORSproxy object. This object is just a convenience object, you could equally well create an ADO recordset object directly, but using this object makes it simpler.

The Test Object

The ComBridge system comes with a test COM object, ComBdgTestObj.exe. This will be automatically registered and placed in either C:\Program Files\Octatec\ComBridge  or a directory of your choosing during installation. This object is used by the cbtest client test program, and the UseComBridgeSrvr test program.

The Interactive Test Utility

The ComBridge system comes with an interactive  test utility, UseComBridgeSrvr.exe. Again, this is placed in either C:\Program Files\Octatec\ComBridge  or a directory of your choosing during installation. It is not added to a menu or the desktop, so you will have to use Windows Explorer to locate it in the file system and double click it to start it. The menu options are self explanatory; the mostt interesting one is the Server Tests menu, which runs a series of tests against the localy installed server.


Server Side Installation Guide

To install the demo server, simply download the self installing EXE and double-click it. If you order the full version, you will be provided with a similar self installing EXE. The process is extremely fast and simple - it does not require a reboot, and it does not add, or modify any system/shared DLLs


Server Side Configuration Guide

There are a few registry entries that you can modify to configure the ComBridge Server.

Server Registry Entries

These parameters are located under the following registry key

HKEY_LOCAL_MACHINE\SOFTWARE\Octatec\ComBridge\1.00

AllowClients
This is a single string of space separated ip-addresses that are allowed to use the server, E.G. "129.32.10.1 132.76.12.5" Note: it must be the actual ip-address and not the hostname that appears in the string. If you have the hostname but don't know the ip-address, use the ping command to determine it. If you want to allow all ip-addresses to access your system, set the string-value to a single asterisk (*). If you want to prevent any ip-addresses from connecting, set the string-value to a singe hash (#).

ExcludeClients
This is a single string of space separated ip-addresses that are not allowed to use the server. If an ip-address appears in both the AllowClients and ExcludeClients parameters, the ip-address will be excluded. If AllowClients is set to *, clients in the Exclude list will still be excluded.

Port
This is a string parameter that contains the port used by the ComBridge server. By default, this is 1082. If you get "Can't Bind" errors, it probably means the port is used by another program, so in such cases, you should change the value of this parameter. NB, if you change this parameter, you must remember to inform all your clients.

Logging
You can switch logging On or Off using this string-value. A value or 1 indicates ON, and 0 indicates off. The log file is written to %TEMP%\ComBridgeSrv.log. You should normally have logging switched off - if errors occur they will still be recorded in the log file even with logging off. (NB this parameter is ignored by the EXE-based server - logging is controlled from the user interface).


Client Side Components

  • ComBridge Library (libComBdg.a)

  • This library allows your application to use any COM or DCOM Automation object on any WIN32 system running the ComBridge server
  • ComBridge Library C++ headers (./lib/*.h)
  • Test program (cbtest)

  • This test program calls methods on the test object on the server. It is supplied in source code form.
Two directories will be added to your system ./lib and ./cbtest. Further information can be found in the Client Side Installation Guide. The library can be configured using some environment variables, these are covered in the Client Configuration section

System Requirements

There are no special system requirements, you just need a UNIX system. ComBridge uses the standard sockets API for network access
 

The Client Library And Headers

The client library is a C++ class library named libComBdg.a. It contains the following classes.( These classes are covered in more detail in the section dealing with the ComBridge API.)
 
  • ComBridge    "ComBridge.h"

  • this class implements the actual communications link to the server - it is the first class you will create.
  • IDispatchBridge  "IDispatchBridge.h"

  • this class implements access to the COM/DCOM IDispatch object
  • RecordsetBridge    "RecordsetBridge.h"

  • this class simplifies the use of ADO recordsets, and implements Bulk Transfer of records to improve performance
  • _Variant    "Sarray.h"

  • this class acts as a holder for the various types that can be accepted by ActiveX Automation objects
  • Sarray    "Sarray.h"

  • this class implements an array which can be sent to or received from IDispatch objects
  • _DateTime    "DateTime.h"

  • this class encapsulates the DATE type used by ActiveX Automation, it provides a great deal of functionality, and is a useful class in its own right
  • _Currency    "Currency.h"

  • this class holds a CURRENCY ActiveX Automation,  type, it provides no other functionality other than the data it contains.
The make_app shell script utility that builds the cbtest program shows how to link in libComBdg.a for your version of UNIX.
 

The cbtest Test Program

Usage:     cbtest hostname [port]

This program creates a ComBridge to the named host and calls some internal data transfer test functions. It then creates the Test Object and calls methods on it.
The source code is supplied with the installation and provides a detailed example of how all data types can be passed and received. Included in the tests are calls to object methods that return ADO recordsets. To build cbtest, cd  to the cbtest sub directory which will be created after you have installed the ComBridge client package, and type make_app.
 

Inside cbtest

Main.C processes the command line and calls the TestDataTypes() function that calls functions that test ComBridge's low level data transfer methods, and then tests  ComBridge's higher level methods by using the test object. The test methods are all contained in DataTests.C. The functions that will be of most interest to the programer, and demonstrate the API are...
  •   OnCallObject1();
  •   OnBigStringTest();
  •   OnTestArrayString();
  •   OnTestObjSimpleVar();
  •   OnTestObjectMDimArray();
  •   OnTestObject3dArray();
  •   OnTestObject4dArray();
  •   OnDateTest();
  •   OnDateArrayTest();
  •   OnCyTest();
  •   OnCyArrayTest();
  •   OnTestDblArray();
  •   OnTestReturnIdispatch();
  •   OnAdoRecordSetTest();
  •   OnAdoBulkTest();
The functions are named so as to describe the tests they perform, the OnCallObject1() function performs general tests and is a good place to start.


Client Side Installation Guide

The client side installation is downloaded as a Compressed tar file, ComBdg.tar.Z.. You simply uncompress it and extract the files. You can do this in any directory. Then you just build the test program, cbtest, and run it. The following commands are all you need...

$ uncompress ComBdg.tar.Z

 NB the name of your tar file will be different, depending on the Unix/Linux version you have downloaded
$ tar xvf ComBdg.tar
$ cd cbtest
$ ./make_app
NB: you may find the name of the Compiler in this script is not the same as the one on your system,  this is quite likely on Linux systems, the compiler in the script is CC, whereas you may find it is  g++ on your system.
$ ./cbtest $WIN32_SERVER

You must have already setup the ComBridge server on a WIN32 system in order to run cbtest successfully. In the above example $WIN32_SERVER is the hostname or IP-Address of the system where the ComBridge server is loacated..


Client Side Configuration Guide

There are a few environment variables that you can set to configure the behaviour of the ComBridge Client Library.

$COM_BRIDGE_PORT
The default port used to connect to the server is 1082. This can be changed by setting this environment variable. The programmer can override this functionality by explicitly setting a port in the code.

$COM_BRIDGE_LOGGING
If this environment variable is set to "1", the ComBridge Client Library will write logging information to /tmp/ComBridgeClient.log. Even if this is set to "0", errors are still recorder in the log file.

$COM_BRIDGE_LOG_FILE
The log file can be changed from the default by setting this environment variable. The length of the log file name must be less than 64 characters. The programmer can override this functionality by explicitly setting a log file name in the code



 

Client-Side Programing Guide

Introduction to ActiveX Automation

ActiveX Automation Objects are objects that implement the IDispatch interface. Basically an Automation object has a list of methods, each identified by a unique number. To call a method you pass the object the methods number and a list of arguments, you then get back a return value and any return arguments provided by the method. Automation objects are usually described by an ODL (object definition language) or IDL (interface definition language) file, which is very similar to a C++ header.

A word about CORBA...

ComBridge is not a CORBA implementation but it could be used to allow CORBA objects to call ActiveX Automation objects, i.e. it could be used to implement CORBA wrappers for ActiveX Automation objects - simply write a CORBA object with the desired methods, and embed calls to ComBridge within the body of the CORBA methods.

ComBridge API

The ComBridge API has been designed to be very easy to use. In order to connect to a remote COM object, you simply create a ComBridge to the server system as follows
    char *hostname = "some-win32-host";
    ComBridge comBridge;
    if( !comBridge.Connect(hostname) )
        // ...report error...
Then to access a COM Automation object on the server, you create an IDispatchBridge to the object, using the ComBridge object already created.
    IDispatchBridge object(&comBridge);
    char *objectName = "ComBridgeTest";
    object.Create(objectName);
Then you 'prepare' the method you are going to use. In order to do this, and latter steps, you will need the ODL (or IDL) of the object you are going to use. The following is an extract for the ComBridgeTest's ODL.
    [id(2)] BSTR ToUpper(BSTR str)
Using the method id (2) we can 'prepare' the method (the ToUpper method takes an input string and converts it to upper case and returns it)
    object.PrepareMethod(2)
Then we 'push' all the arguments. (NB: BSTR is equivalent to char*, see the section about Automation Types for more information). NOTE: it is your responsibility to ensure that the parameters you push are the correct type and are in the correct order. If they are not you will get and error return from the Invoke() method. [NOTE: Arguments can be input/output, in which case the address of the variable is passed in, or input only in which case the variable itself is passed in. input/output variables will change value after Invoke() has been called and all pointers to non-simple types (e.g. pointer to strings, i.e. char**) must be deleted after use - if you just pass in a char* you don't need to deleted it (at least, not as a result of passing it to an IDispatchBridge method ) unless, that is, you passed it to the Invoke method which takes a reference as an argument. (you will, of course, need to delete any object you previously new'd). The important point is: complex output parameters and return parameters are allocated by ComBridge and must be deleted by you if your program isn't to leak memory,
    char *input = "to-upper";
    object.PushArg(input);
Once all the arguments have been pushed, the method can be invoked
    char *returnValue = NULL;
    object.Invoke(returnValue);
    //... use returnValue ...
    delete [] returnValue;
NB: it is the callers responsibility to delete strings that have been returned by IDispatchBridge methods.

A more complex example is the TestByRef method. This method takes 3 input/output parameters. (NOTE: IDL files will usually contain the 'direction' of the parameter in square brackets, whereas ODL files do not). The method appends the string "+StringByRef" to the input string, it adds 9999.99 to the input double parameter and 1000 to the input long parameter. The ODL description of the method is...

    [id(5)] long TestByRef(BSTR* pBstr, double* pDBl, long* pLong);
The method is called as follows
    object.PrepareMethod(5);
    char *s = "String";
    object.PushArg(&s); // note it is &s that is passed because the ODL uses BSTR*
    double d = 0.0;
    object.PushArg(&d);
      long l = 0;
    object.PushArg(&l);
    long returnValue;
    object.Invoke(returnValue);
    // ... the addresses passed into the PushArg method will now contain the new values
    // ... NB: if the input char pointer had been new'd, you would have to take care since
    // ... the output pointer s will point to a different location and you run the danger of
    // ... leaking memory
    delete [] s; // you must delete pointers returned by IDispatchBridge methods
There is a fair degree of scope for errors in passing the wrong type, and to reduce this, a code generator that reads IDL and ODL files and produce IDispatchBridge wrapper classes is planed for the near future.

Now we will look at methods that actually return objects from the Server. The following method in the test object returns an IDispatch pointer in an output parameter...

[id(22)] long GetDispTestAsParam(IDispatch** lpDisp);
Whenever you see a method that returns an IDispatch pointer as either a parameter or a return value, you should pass in a NULL initialized pointer to an IDispatchBridge object, E.G.
object.PrepareMethod(22);
IDispatchBridge *pdisp = NULL;
object.PushArg(&pdisp);
long result;
object.Invoke(result);
// pdisp will now point to an IDispatchBridge object that you can use, and then must delete
delete pdisp;
Another example receives an object pointer as a return value...
[id(20)] IDispatch* GetDispTestAsReturn(long* result);

object.PrepareMethod(22);
long result;
object.PushArg(&result);
IDispatchBridge *pdisp = NULL;
object.Invole(pdisp);
// ... call methods on pdisp...
delete pdisp;
 

The final example presented here receives an ADO recordset pointer. An ADO recordset is just an IDispatch object with a set of well known methods.
[id(21)] long GetAdoRecordset(BSTR database, BSTR query, IDispatch** lpRecordset);

object.PrepareMethod(21);
char *database = "unused-paramter";
object.PushArg(database);
char *query = "unused-parameter";
object.PushArg(query);
IDispatchBridge *pRecordset=NULL;
object.PushArg(&pResordset);
long result;
object.Invoke(result);
//...use the recordset...

(You are probably wondering about the unused parameters. In a previous version of the test object, a database and a sql-query-string were required. However, there was a problem with this - You might not know the name of a database (or even have access to one) when you run the test. Now, the test object 'manufactures' a standard ADO recordset and returns it, ignoring the database and query  parameters. Of course, this behaviour is specific to the test object, and if you want to use ADO recordsets for real, you will have to know a database name and a sql-query-string.)

You may call all the methods on the ADO recordset by using PushArg and Invoke, however, there is a wrapper class (RecordsetBridge) which makes the use of ADO recordsets easier and faster.
RecordsetBridge adoRS(pResordset);
adoRS.InitializeBulkFetch(); // improve speed of data access
long n = adoRS.GetCount();
for(int i=0; i<n; i++)
{
    adoRS.GetNextRow();
    long columnOne;
    adoRS.GetColum("NameOfFirstColumn", columnOne);
        // read the columns by name into variables - you
        // must know the correct column type - if you do not
        // you can pass in a variant...
    _Variant v;
    adoRS.GetColumn("NameOfSecondColumn", v);
        // if you don't know the name of the column you
        // can pass in a position
    adoRS.GetColumn(3, v);
}

// because we passed the pResordset pointer to a RecordsetBridge
// we do NOT have to delete it, the RecordsetBridge will delete
// it in its destructor
 

The source code of cbtest is included as a programing example. The above extracts are taken from cbtest. Note: in the above examples the return values are not tested; in practice they should be tested, a value of 0 indicates success.

The ADORSproxy Object

This object is an In-Processes Automation Object that exists on the server. It is used to obtain ADO Recordsets from the Server. The ODL for the ADORSproxy looks like...
 
[id(1)] IDispatch* OpenRecordset(BSTR query, BSTR connectionString,
                    long openFlag, long lockFlag, long optionFlag, boolean disconnectedMode);
[id(2)] long GetLastError();
 It is used as follows...
char *hostname = "some-win32-host";
ComBridge comBridge(hostname);
comBridge.Connect(hostname);

IDispatchBridge ado_rs_proxy(&comBridge);
if( ado_rs_proxy.Create("ADORSproxy") != 0 )
    // report error

ado_rs_proxy.PrepareMethod(1);

char *query = "some_sql_query";
char *connection = "DSN=???;UID=???;PWD=???";
long openFlag = -1;
long lockFlag = -1;
long optionFlag = -1;
long disconnected = 1; // TRUE

ado_rs_proxy.PushArg(query);
ado_rs_proxy.PushArg(connection);
ado_rs_proxy.PushArg(openFlag);
ado_rs_proxy.PushArg(lockFlag);
ado_rs_proxy.PushArg(optionFlag);
ado_rs_proxy.PushArg(disconnected);

IDispatchBridge *prs = NULL;
if( ado_rs_proxy.Invoke(prs) != 0 )
    // report error

RecordsetBridge adoRS(prs);
adoRS.InitializeBulkFetch(); // improve speed of data access
long n = adoRS.GetCount();
for(int i=0; i<n; i++)
{
    adoRS.GetNextRow();
    ...
}


Automation Data Types

Only a limited number of data types can be passed to an Automation Object's methods, however this limitation is rarely a problem. The following data types are supported

Simple Types
 
long  short  double 
long*  short*  double *

Complex Types
 
string(char* or _Bstr) _DateTime _Currency Sarray _Variant
pointer-to-string(char** or _Bstr* _DateTime* _Currency* Sarray* _Variant*
IDispatchBridge*




ComBridge API Classes

Link to: libComBdg.a
 
ComBridge

#include <ComBridge.h>

This class is used to set up the connection to the remote WIN32 system.

ComBridge()
Default constructor

bool Connect(char *host=NULL, int port=0)
Connect to the named host using the specified port. If the port is 0, the default ComBridge port (1082) is used, however if $COM_BRIDGE_PORT is set, and the input port is 0, the value of $COM_BRIDGE_PORT will be used. The method returns true if successful.

void Disconnect()
Disconnect the current connection

int GetErrno()
If an error has occurred, this method returns the error number

bool IsConnected()
Return true if the object is connected

static void SetLogfileName(const char *name)
You can use this to specify the log file written to by the library. If you use this method, the environment variable $COM_BRIDGE_LOG_FILE will be ignored.

static void SetLoggingOn(bool mode)
You can use this to programmatically set logging on (mode=true) or off (mode=false). This will override the shell variable that normally controls logging, $COM_BRIDGE_LOGGING will be ignored.

~ComBridge()
The destructor will close any open connection
 
 
IDispatchBridge

#include <IDispatchBridge.h>

This is the most important class. It allows you to create an ActiveX Automation Object on a WIN32 system. pass it parameters and call methods on it. All methods that return int, will return 0 on success, and a COM error code on failure. A NULL-initialized IDispatchBridge pointer can be passed to methods that are defined as taking an LPDISPATCH* (or IDispatch**) in the ODL/IDL - if this is done you must delete the returned IDispatchBridge pointer yourself.

IDispatchBridge(ComBridge *pServer)
Constructor - IDispatchBridge objects are created by passing them a pointer to an already connected ComBridge object. At this point no Automation object is created, you must use the Create() method to do that.

int Create(char *clsID)
Create the object on the remote system. You need to know it's class-id or class name to do this. In the case of the ComBridge test object, it's name is ComBridgeTest. The method returns 0 on success, otherwise a COM error code is returned.

int PrepareMethod(long dispID)
Once you have created an object, you are ready to call methods on it. To do this you must 'prepare' a method - call PrepareMethod() with the methods DISPID. You will get the DISPID from the ODL or IDL file that describes the object. In order to successfully call an Automation Object you will need to see its IDL or ODL file.

int PushArg(TYPE  value)
Once a method has been prepared, you can pass it arguments. You do this by calling PushArg repeatedly with all the arguments that the method requires. It is the programers responsibility to pass the correct arguments in the correct order. The TYPE in the methods argument list represents one of the valid Automation types, these are: long, short, double, string(char*), _LPDISPATCH*,  DATE, Variant, _Currency

int PushArg(TYPE  *value)
Instead of passing the argument by value, you can pass it by reference. You should do this if the ODL/IDL specifies the argument is a pointer. This is usually done if the method is expected to change the value of the parameter, i.e. it is an output parameter. The TYPE in the methods argument list represents the the same Automation Types listed above, with the addition of IDispatchBridge - you may receive objects in output parameters but you cannot pass an object to an Automation Method.  Note: if the TYPE is a string(char **), or an IDispatchBridge** the pointer MUST be initialized, and in the case of IDispatchBridge** it must be initialized to NULL. The returned object must be deleted after use if your program isn't to leak memory.

int Invoke(TYPE &returnValue)
Once You have pushed all the arguments you can invoke the method. To do that call Invoke. You must know the correct return type of the method, and pass a suitable variable to receive the value. If the method has no return type, don't pass anything. The type of the returnValue is specified  if the IDL or ODL. It is slightly different in ODL files to IDL files. In ODL files it will specified just as in a standard C++ method definition However in an IDL file, all methods will be defined as returning an HRESULT (Error Code), the actual return value is specified as an output parameter with a description of  [retval,out] immediately preceding it - such return values in IDL files will always be specified as pointers, but when you call Invoke, you don't pass a pointer, unless the IDL files specifies a pointer-to-a-pointer. Note: once Invoke has returned any arguments 'passed-by-value' will automatically have been updated with their new values. If you pass in references to char* or IDispatchBridge* the returned pointer must be deleted after use.

int GetProperty(TYPE &returnValue)
In some circumstances, you will not call Invoke, but rather GetProperty(). This is the case when you want the value of a property. You will know to call GetProperty because the method will be prefixed with [propget] in the IDL or ODL file.

int PutProperty()
In other cases, i.e. when you are setting a property of an object, you will cal PutProperty instead of Invoke. You will know that you must cal this method if the OLD or IDL file prefixes the method name with [propput]. If you call Invoke() for a method that you know exists, and you get an error return (i.e. something other than 0) and you are sure the DISPID and parameters are correct, it may be that the method is implementing a property, in which case you will need to call PropertyGet() or PropertyPut() - normally PropertyPut() methods will only require one input argument and have no return value, while PropertyGet() methods will not have any input arguments and have a return value.

int Release()
Release (i.e. destroy) the remote object - you don't need to call this method, it is automatically called in the destructor.

~IDispatchBridge()
The automation object  on the remote system is automatically released when the IDispatchBridge is destroyed.
 
 
RecordsetBridge

#include <RecordsetBridge.h>

This class wraps up the ADO recordset class, making it easier to use. ADO recordset are the 'modern' way of receiving data from databases. They are returned in the form of IDispatchBridge objects from WIN32 COM Automation Objects. As such, you can call all the methods on the object directly using IDispatchBridge methods, and do not need to use a RecordsetBridge at all. However, using a recordset bridge makes things much easier, and also improves performance with a ''bulk fetch'' option.

RecordsetBridge()
The default constructor - after construction an object it this way, you must call the Attach() method

RecordsetBridge(IDispatchBridge *pADOdisp, bool takeOwnership=true)
This is an alternative way to construct a RecordSet bridge object. The pADOdisp parameter is an IDispatchBridge object returned by an Automation Object. If  the takeOwnership parameter is true, the pADOdisp pointer is deleted in the RecordsetBridge destructor.

void Attach(IDispatchBridge *pADOdisp, bool takeOwnership=true)
If the default constructor is used, you must call this method to attach an ADOrecordset object to the RecordsetBridge.

bool GetNextRow()
Once the RecordsetBridge object has been attached to an ADOrecordset, you can begin iterating the records in the recordset. To do this, you repeatedly call this method until it returns false. Note: you should call this method before you try to access the first record.

bool GetColumn(const char *name, TYPE &value)
To access column-values in the record, call this method. TYPE can be one of  long, double, char*, _DateTime or _Variant. If you don't know the type of the data or if it is not one of long, double, char* or _DateTime, use the _Variant type. If the type is wrong or if the value is database-NULL, the method will return false - to test for database NULL, call ColumnIsNull() after GetColumn() returns false.

bool GetColumnAt(long pos, TYPE &value)
This method provides a way to access columns by position rather than by name, apart from that it is the same as the GetColumn() method.

bool ColumnIsNull()
This method returns true is the last column whose value you tried to retrieve was database-NULL.

long GetLastError()
If any method fails, this will return the last COM error code.

bool InitializeBulkFetch(long rowsPerBlock = -1)
You can call this method immediately after attaching a recordset to the bridge in order to improve performance. As its name suggests, the method will arrange for records to be fetched  in bulk from the server, thus reducing network calls. The GetNextRow(), GetColumnm() and GetColumnAt() methods work in just the same way whether or not bulk fetch has been initialized. If rowsPerBlock is -1, the whole recordset will be fetched in one network request. You can set rowsPerBlock to any value.

long GetRecordCount()
This method will return the number of records in the recordset. However, it is not guaranteed to work, it may return -1 depending on the type of recordset you actually have. There are many types of ADOrecordset; if the type is 'disconnected' the GetRecordCount() method will work, otherwise it will return -1. NOT: if the record count is not available, InitializeBulkFetch() will set the rowsPerBlock to 100 if it is called with rowsPerBlock set to -1.

~RecordsetBridge()
The destructor will delete the IDispatchBridge to which it was attached if the takeOwnership parameter in the Constructor or in the Attach() method was true.
 
 
Sarray

#include <Sarray.h>

The Sarray class is used to transfer arrays of data to Automation Objects. In practice it is never used on its own, it is always contained within a _Variant. The ComBridge's implementation of the Sarray limits it to 4 dimensions. The Sarray is limited to the following automation data types: long, short,double,_Variant,_Date, _Currency.   The  type is indicated by the _VariantType Enumeration found in Sarray.h. Use Sarray whenever a VARIANT containing a SAFEARRAY is specified

Sarray()
The default constructor. If you construct an Sarray in this way, you will have to use the Init() method to set its size and type.

Sarray(unsigned char type, unsigned char numberOfDimensions, SarrayBound *pbounds)
This method creates an array of the given type, with the specified number of dimensions. The upper and lower bound of each dimension is specified by the array of SarrayBounds structures, these structures have the members unsigned long m_lowerBound  and  unsigned long m_size; usually m_lowerBound will be 0, but it need not be. As in all methods that take a type parameter, it must be one of _VT_LONG, _VT_SHORT, _VT_CY, _VT_DOUBLE,  _VT_DATE, _VT_STRING, _VT_VARIANT.

Sarray(unsigned char type, unsigned char numberOfDimensions, int *sizes)
This version of the constructor provides a slightly simpler way of creating an Sarray object, in that it assumes all lower bounds are 0, and then just needs an array of integer sizes for each dimension.

Sarray(const Sarray &rhs)
The copy constructor

Sarray &operator = (const Sarray &rhs)
The assignment operator

bool Init(unsigned char type, unsigned char numberOfDimensions, SarrayBound *pbounds)
This method provides a way to create an Sarray after it has been constructed.

bool Init(unsigned char type, unsigned char numberOfDimensions,  int *sizes)
This method provides a simpler way to create an Sarray after it has been constructed, assuming all dimensions lower bounds are 0.

void *GetAt(int *pIndices)
This method provides a way to access elements of an array. You should cast the returned pointer the desired type. The pIndices parameter points to an integer array specifying the indices of the element to set.

bool SetAt(int *pIndices, void *pdata);
This method provides a way to set elements of an array. You should cast the input pdata address to void*. The pIndices parameter points to an integer array specifying the indices of the element to set.

const SarrayBound *GetDimensions() const
This method returns the SarrayBounds structure that defines the bounds of each dimension.

unsigned char GetNumberOfDimensions() const
Get the number of dimensions

unsigned char GetType()  const
Get the type of the array, the return value is one of  the _VariantType enumeration values .

unsigned long GetSize() const
Get the total number of elements in the array.

Empty()
Free any memory, and set the type of the array to _VT_EMPTY.

There are many examples of using the Sarray and _Variant classes in the cbtest source code, included in the client distribution.
 
 
_Variant

#include <Sarray.h>

This type is used to pass data and a description of the data, i.e. its type. To use a  _Variant you must assign the m_type member to one of the _VariantType enumeration values. You then assign one of the following members, depending on the type. USe this type whenever you see VARIANT specified in the ODL/IDL file.

long               m_l
long              *m_pl
short              m_i
short             *m_pi
double             m_d     /* also DATE */
double            *m_pd    /* also DATE * */
char              *m_s
char             **m_ps
_Currency          m_cy
_Currency         *m_pcy
Sarray             m_a
Sarray            *m_pa
IDispatchBridge   *m_pdisp

_Variant& operator = (const _Variant &rhs)
The assignment operator

~_Variant
The destructor, it will automatically free any memory allocated.
 
 
_Bstr

#include <Sarray.h>

This is simply a char* (or char** for a pointer to a string). Use _Bstr whenever the ODL/IDL specifies BSTR and user _Bstr* whenever the OLD/IDL specifies BSTR*. It is important to understand that if you pass a pointer to a char* to a method to receive an output value or receive a char* as a return value (i.e. a char* parameter to the Invoke method), the char * pointer will have been newly allocated when the method returns and must be deleted by you when you no longer need it. It follows from this that if you allocate a char* on the heap, and then pass its address to an IDispatchBridge method, the pointer will come back pointing at a different location, and you will leak the memory that the pointer originally pointed to unless you make another copy of the pointer before you pass its address to IDispatchBridge.
 
 
_DateTime

#include <DateTime.h>

The _DateTime class is used transfer DATE information between Automation objects. It has many members that facility its use. The public member m_date is the only state information held by a _DateTime object, this is a double precision value, and it is that value that is actually passed to the Automation object. The header defines DATE to be a double. The _DateTime type is basically a wrapper for an OLE DATE which is a double precision floating point number, the fractional part represents the time of day, and the whole part represents the number of days. Dates start from 1/1/100 AD,  and the value of this date is   -657434.  Jan 1st 1900 is 2.0, Dec 30 1899 is 0, Dec 31st 1899 is 1.0. Use this type whenever the ODL/IDL specifies the DATE type. The _DateTime class wraps up the double precision date and provides a variety of useful access/assignment/arithmetic methods, making it a useful class in its own right.

_DateTime();
_DateTime(const DATE dDate);
_DateTime(const _DateTime &rhs);
_DateTime(const struct tm *tmIn, const short nMs=0);
_DateTime(const time_t tTime);
_DateTime(const char* szDate, const bool fUsMode=false);
Constructors. Note the string szDate is interpreted as "MM/DD/YYYY HH:MM:SS" or "DD/MM/YYYY HH:MM:SS" is fUsMode=true.

operator==(const _DateTime &rhs) const
operator> (const _DateTime &rhs) const
operator< (const _DateTime &rhs) const
operator>=(const _DateTime &rhs) const
operator<=(const _DateTime &rhs) const
Logical operators.

short GetHour()const               void SetHour(short nHour)        void SetMonth(const char* szMonth);
short GetMinute()const             void SetMinute(short nMin)
short GetSecond()const             void SetSecond(short nSec)
short GetDay()conts                void SetDay(short nDay)
short GetMonth()const              void SetMonth(short nMon)
short GetYear()const               void SetYear(short nYear)
short GetMilliSecond()const        void SetMilliSecond(short nMs)
short GetJulian() const            void SetJulian(short nDays, short nYear=0)
Accsessor methods. NB: the SetJulian() method assumes the current year unless the nYear parameters is specified.

_DateTime& AddDay(long nDay=1);
_DateTime& AddHour(double nHour=1.0);
_DateTime& AddMinute(double nMinute=1.0);
_DateTime& AddSecond(double nSec=1.0);
_DateTime& AddMilliSecond(double nMili=1.0);
_DateTime& AddYear(short nYears=1);
_DateTime& AddMonth(short nMonths=1);
Arithmetic methods

bool IsLeapYear(long year=0)
If year is unspecified, the year in the current object is used, otherwise the specified year is used.

const char* Format(char *usrBuff, char cFmt=0) const
Formatting method, the cFmt can be one of
 
FMT_UK_MS : MM/DD/YYYY HH:MM:SS.mmm  FMT_US_MS : DD/HH/YYYY HH:MM:SS.mmm
FMT_UK : MM/DD/YYYY HH:MM:SS FMT_US : DD/HH/YYYY HH:MM:SS.mmm
FMT_US_DATE : MM/DD/YYYY FMT_UK_DATE : DD/MM/YYYY
FMT_STRING : DD MMM YYYY HH:MM:SS  FMT_TIME : HH:MM:SS
FMT_STRING_MS : DD MMM YYYY HH:MM:SS:mmm FMT_TIME_MS : HH:MM:SS:mmm
FMT_STRING_DATE : DD MMM YYYY FMT_ODBC : YYYYMMDD

The user must ensure the buffer is large enough to take the formatted string.

struct tm GetAsTmStruct()
Get a tm stuct from a _DateTime object.
 
 
_Currency

#include <Currency.h>

Use this type whenever the ODL/IDL specifies the CURRENCY or CY type. This is a structure containing 2 longs. This type can be passed and received, but there is no additional support for it, and if you use it you will have to program such things as formatting and arithmetic yourself. This will be considerably easier if your compiler supports 64 bit integers.


Home | FixGateway | AFI/J | SimpleGrid | SBpayroll | SXAzip | InstallScript | DiskUsage/DiskClean | Virtual Desktop Manager | ComBridge | Demos | Purchase