Home > The CATIA Object Model > Working with restricted interfaces

Working with restricted interfaces


Often times when coding in VBA, you may get an error message that says, “Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic.”  In this article, I will explain the reason for this error and present a good strategy to deal with it.

When does the error occur?

First off, you will only see this error when you work in VBA or another programming language/environment where you are able to early bind data types.  You will not see this error in VBScript programs because all variables are always late bound.  If you are not familiar with the concept of binding, early binding simply means that you have declared a variable in your program as a specific type and the compiler associates that type information to the variable before the program begins executing.  On the other hand, late binding means that the specific data type of the variable is discovered as the program runs.  If you browse the automation API help documentation, you might notice that all CATIA automation objects support the IUnknown interface which is what makes this discovery possible at runtime.

You will get this error any time you early bind on a CATIA automation object and then call a method that has an array argument.  For example, one of the most common situations is when programming an interactive selection in your program.  There are several different methods available to handle selections and they all require an array to define a filter of what types of objects can be selected.   Below I will show the selectElement2 method:

'Prompt the user to select a body or geometrical set
Dim varFilter(1) As Variant
Dim objSel As Selection
Dim strReturn As String
Dim strMsg as String

varFilter(0) = "Body"          'Body represents a solid body
varFilter(1) = "HybridBody"   'HybridBody represents a geometrical set
Set objSel = CATIA.ActiveDocument.Selection
strMsg = "Select a body or geometrical set…"
objSel.Clear
strReturn = objSel.SelectElement2(varFilter, strMsg, false)

'Display the name of the selected item
Msgbox objSel.Item2(1).Value.Name

You can see that on line 3, I declared the objSel variable as a Selection object (this is the early binding).  Then on line 12, I try to call the SelectElement2 method which takes an array as an argument.  This will generate the error.

Another common offender is the Measurable object which, you guessed it, is used to perform various types of measurements.  This object has many different methods that take an array as an argument.

'Measure the x,y,z coordinates of a point
Dim varCoords(2) As Variant
Dim objPart As Part
Dim objPoint As Point
Dim objRef As Reference
Dim objSPAWorkbench As Workbench
Dim objMeasurable As Measurable

'Retrieve Point.1 from the first geometrical set in the active part
Set objPart = CATIA.ActiveDocument.Part
Set objPoint = objPart.HybridBodies.Item(1).HybridShapes.Item("Point.1")
Set objRef = objPart.CreateReferenceFromObject(objPoint)

'Measure the coordinates of the point
Set objSPAWorkbench = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench")
Set objMeasurable = objSPAWorkbench.GetMeasurable(objRef)
objMeasurable.GetPoint varCoords

'Display the coordinates
Msgbox Join(varCoords, ", ")

You can see on line 7, the Measurable object was early bound and finally on line 17 the GetPoint method was called which will generate the error.

How to best deal with this situation

The CATIA help documentation recommends that you simply do not declare the type when you plan to call one of these methods.  This is definitely the easiest technique, and it is a good stategy in some situations.  However, I really try to fully declare all of my variables as much as possible so that I can take advantage of the compiler’s ability to find all kinds of different mistakes in my code.  This strategy can save a ton of time and headaches down the line when you are trying to track down and fix bugs in your program.  So what strategy is best?

  1. If you only plan to make a single call to the object, just skip the type declaration as recommended above or declare the variable as Object or As Variant.  This will allow the object to be late bound and avoid the error. You really don’t have any other choice here.
  2. If you will make more than one call to the object (as in the earlier selection example) you should declare 2 separate variables to work with.  The first one should be fully declared with the type and the second one will omit a specific type.  I then make both variables refer to the same object in memory then I use the untyped one to make the calls requiring an array and the typed one for all other calls.  This way, I can still take the fullest advantage of the compiler to catch mistakes.  Below, I have modified the earlier mentioned selection example to follow this strategy.
'Prompt the user to select a body or geometrical set
Dim varFilter(1) As Variant
Dim objSel As Selection
Dim objSelLB As Object   ' <--- notice declared as object
Dim strReturn As String
Dim strMsg as String

varFilter(0) = "Body"            'Body represents a solid body
varFilter(1) = "HybridBody"      'HybridBody represents a geometrical set
Set objSel = CATIA.ActiveDocument.Selection
Set objSelLB = objSel
strMsg = "Select a body or geometrical set…"
objSel.Clear
strReturn = objSelLB.SelectElement2(varFilter, strMsg, false)
If strReturn = "Normal" Then
   If objSel.Count2 > 0 Then
      Msgbox objSel.Item2(1).Value.Name
   End If
End If

In this example, you can see that on lines 3 and 4 I declared two different variables for the selection.  Then on line 10, I assign the selection object for the active document to the objSel variable then on line 11 assign that same object to the objSelLB variable.  Realize that in memory there is only one Selection object but you are allowed to have many different variables point at that same memory address which is what I am doing here.  By pointing two different variables at the same object, that same object can be accessed by different variables that are typed differently.

In the remaining code, you can see that I make a total of four calls to the selection object.  Three of them were handled from the objSel variable which was fully typed.  This allows the compiler to catch any coding mistakes I might have made in three different places that would have been overlooked if I had just used a single variable whose type was not declared.  Then the untyped variable is used to make the call that requires an array argument which avoids the restricted interface error.   Here, gaining three places where the compiler can help us find errors might seem insignificant but in a larger program that could easily grow to 50 places or more.

Conclusion

In this article, I explained why this common error occurs.  There are hundreds of places in the CATIA automation API where you can potentially encounter this issue so it is important to understand what causes it and how to deal with it.  The strategy I presented at the end of the article covers some interesting programming concepts related to variables and memory as well as debugging.  I hope it all made sense, but if not just post a comment and I will try to explain a bit more.


Add to: del.icio.us del.icio.us, StumbleUpon StumbleUpon, Digg Digg, Google Google

About these ads
  1. Karteek
    August 1, 2010 at 2:28 am

    Really nice one! I generally do not declare my variables as specific types. But learned a lot about the error. Thanks

    Karteek

  2. Sameer
    August 23, 2010 at 6:17 pm

    This is really helpful. Thanks for putting effort to describe the cause and solution in detail.

  3. Nick
    November 9, 2010 at 6:50 pm

    You are a lifesaver! For other people’s info, if you’re using the Factory2D objects and get this error on a line for MyFact2D.CreateSpline or similar, use the above method on the Factory object, not the object you’re creating. For instance

    Dim NewSketchFact As Factory2D
    Set NewSketchFact = NewSketch.OpenEdition()
    Dim SketchFact2
    Set SketchFact2 = NewSketchFact
    Dim NewSplineObj As Spline2D
    Set NewSplineObj = SketchFact2.CreateSpline(RPointObjects)

  4. February 25, 2011 at 6:16 am

    Nick ! your post about the spline creation with Factory2D really helped me ! so thank you very much.

  5. Pavel
    March 1, 2011 at 5:45 am

    Hi,
    thank you so much for this article. It really helps me to solve my problems!
    Pavel

  6. François
    August 31, 2011 at 10:42 am

    Thanks for the tip!
    You’re blog so good! Bookmarked!

  7. Sunil
    April 25, 2012 at 12:09 am

    Hi,
    Thanks for the article

  8. George
    October 8, 2013 at 8:34 am

    Hi,
    Yes great write up thanks. One question :
    Why do you get an error when you do early binding on a CATIA automation object and then call a method that has an array argument. This part does not make sense to me.
    Thanks

  9. Jean-Philippe
    May 3, 2014 at 11:19 pm

    HI,
    Thanks a lot, your article (and your website) allowed me to save a lot of time already. Thank you sincerely for making my life easier :)

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 141 other followers

%d bloggers like this: