Monday, March 02, 2009

SolidWorks API - In-process or Global methods - Which to use?

Two SWX API to rule them (or is it 'Two SWX API to confuse us'?)
Did you know that SolidWorks (SWX) provides two distinct (yet confusingly similar) interfaces to 'get' or 'set' arrays through its API? Well it does. I recently installed SWX 2009 SP 2.0 (I know, I know - this release has been out for a while, but I never needed the newer features) - but I upgraded from SWX 2007 SP 0.0 when I ran into some vexing problem with the SWX API and hoping that it was an SWX bug, decided to try their newest version. Turns out the problem were me and my limited knowledge of these two API interfaces.

The one advantage of installing SWX 2009 was the updated API documentation. The 2007 API documentation did not contain a page titled "In-process methods", which the 2009 version does. The following is an excerpt from that SWX 2009 API page (apihelp.chm) (italics are my addition) (note to lawyers: if it is not legal to publish portions of the SWX help documentation, please leave a comment and I will remove the appropriate sections)

In-process Methods
The SolidWorks API provides two types of methods for interfaces that get or set arrays:
  • in-process
  • global
For example, IView contains these methods:
  • IView::IGetCThreads (in-process)
  • IView::GetCThreads  (global)
Both types of methods perform the same work, but each is more or less appropriate for a given language and application.
In-process methods typically begin with the letter I and get or set pointers to arrays that only unmanaged C++ applications can handle. The in-process companion methods (i.e., similarly named methods that do not begin with the letter I) are more globally useful both inside a process and across processes and return predictable results for all of the SolidWorks supported languages.
In VBA, VB6, VB.NET, C#, and C++/CLI (also called managed C++), global methods typically get or set a VARIANT or object that the programmer can iterate as an array. In unmanaged C++, these methods get or set a pointer to a Dispatch object that should be cast as a SafeDISPATCHArray. (SafeDISPATCHArray is a VARIANT helper class defined in a template class, which is available on the API Support website.)
Q. To chose or not to chose
So how do you decide which interface to use? Does it even matter?
A. The answer to the 2nd question 'does it even matter' is - simply - YES IT DOES MATTER.

To answer the 1st question 'how do you decide which interface to use' - consider the following:
  • If 
    1. you are building a DLL Add-in to SWX,

      AND 


    2. you plan to only load that DLL through SWX

      THEN

       
    3. you can comfortably use the "in-process method".
  • But if
    1. you are building an EXE that loads SWX through COM

      AND
       
    2. loads your SWX Add-in DLL (i.e. instantiates classes from the Add-in DLL in the EXE), allowing calls from the Add-in DLL to go to SWX

      THEN
       
    3. you need to use the "global method" in

      BOTH
       
    4. the COM+EXE and Add-in DLL.

      AND

    5. LUCKILY YOU CAN STILL LOAD THE DLL ADD-IN DIRECTLY INTO SWX (doesn't that sound ideal?)
So how do you work this "global method"?
If you are like me and have little experience with COM, DISPATCH and VARIANTS then fear not because SolidWorks is gracious enough to provide us with a C++ template to simplify our lives. The files you need are hosted at http://files.solidworks.com/API/Examples/00000/0100s/0126/Example.htm. Simply download the zip file and include the "smartvars.h" file in your solution. The zip file also contains a sample in the file "usage.cpp", but for the sake of completness let me provide you with an example of my own:
VARIANT vxform;
LPSKETCH pSketch;
...
... // code to InsertSketch() so that pSketch is a valid pointer
...
pSketch->get_ModelToSketchXform(&vxform);
SafeDoubleArray varDimArr(vxform);
wofstream wfs;
wfs.open(L"dimension_data_swx3dexpextrusion.txt");
for( int i = 0 ; i < 13 ; i ++ ) {
     wfs << "\nXFormData at\t" << i << "\t=\t" << varDimArr[i];
}
wfs.close();
CONCLUSION
SolidWorks API while easy to work with have a few surprises - though in this case the missing documentation would have spoiled the surprise for me in the 2007 version. So all in all, I am able to run batch-mode integration test using the combination of CEEFIT and "global methods" to access array data from SolidWorks.

2 comments: