Programming with Visual C++

All SAS IOM interfaces are designed to work well with Microsoft Visual C++.
The documentation is written in terms of Visual Basic. This means that the default interface of a component is listed as if it were the interface of the COM object (coclass) itself, even though in pure COM terms, the default interface is just one of many interfaces implemented by the object. Thus, a C++ programmer programs to the IWorkspace interface, even though the Visual Basic documentation shows the methods as belonging to the Workspace object. This section discusses issues with which Visual C++ programmers must be concerned (in addition to the material covered in Programming with Visual Basic ).
All IOM interfaces implemented by SAS are COM dual interfaces. Therefore, methods and property get and set routines can be called as direction entry points with positional parameters. Although IOM interfaces implement an IDispatch interface at the beginning of each v-table, this is only for compatibility with older OLE Automation controllers. Visual C++ programs should not make calls by using IDispatch::Invoke; but should instead call through the v-table entry for the specific method that they want to call. The ClassWizard-generated wrappers for IDispatch (with COleDispatchDriver) should not be used in IOM programming. This feature of Visual C++ is now useful only for interfaces that contain only IDispatch.
All event (also called source) IOM interfaces are COM custom interfaces. This means that callers to the Advise method should pass interfaces that derive only from IUnknown, not IDispatch. All parameters to the event interfaces are only in parameters, which means that none of the interfaces support the ability to return data to SAS through the event interface.
To use the IOM interface in your Visual C++ program, you should import the IOM interface type library. Here is an example:
#import "sas.tlb"
In order for this to work, you must ensure that the type library directory is listed in your include path.
The import statement causes everything in the type library to be placed in a namespace. The fully qualified name for IWorkspace is SAS::IWorkspace. Also see the Using directive in Visual C++, and the -no_namespace attribute on the import statement.
When you import a type library, the Visual C++ compiler creates a comprehensive set of definitions that are specific to that type library by using the helper classes in COM compiler support (as defined through <comdef.h>). The helper classes perform many useful functions, including the following:
  • provide smart pointers for interface references
  • map COM HRESULTs to C++ exceptions
  • use helper classes for BSTRs
  • create wrapper functions that return the IDL-defined return value instead of an HRESULT
  • provide create instance helpers
Programming with the Visual C++ COM compiler support is almost as easy as calling the functions in Visual Basic.
Unfortunately, as of Visual C++ version 6, the COM compiler support is lacking in one important area. There are no wrapper functions for handling safe arrays. You must deal with the OLE Automation safe array API directly.
Dealing with dimensions in this API requires care. You must be particularly careful if you are dealing with two-dimensional arrays. The APIs that deal with safe arrays take a dimension number that is 1-based. In a two-dimensional array, the rows are indexed in dimension 1 and the columns by dimension 2. When you create an input array by using SafeArrayCreate(), the bounds are also passed in this order (the row bounds are passed in rgsabound[0] and the column bounds are passed in rgsabound[1]). Do not be confused by the ordering that you see when you display a safe array structure in the debugger.
Finally, keep in mind that for IOM method calls, lower bounds must always be zero.