Author Topic: COM support broken in Autocad 2012/2013?  (Read 1417 times)

0 Members and 1 Guest are viewing this topic.

SIDESHOWBOB

  • Guest
COM support broken in Autocad 2012/2013?
« on: May 10, 2012, 07:03:07 AM »
I had some C++ code that got called from VL over COM, and returned a safearray of strings.  It worked in Autocad 2011.  Now in 2012/2013, it doesn't.

Can anyone see if I'm doing anything wrong?  If not, could this be a bug introduced in Acad 2012?

Code - C++: [Select]
  1. #include "comutil.h"
  2.  
  3. void string_array_to_bstr_safearray_variant(long arraylength,char ** in_array,VARIANT *out_variant)
  4. {
  5.         CComSafeArray<BSTR> out_array;
  6.         ATLENSURE_SUCCEEDED(out_array.Create(arraylength));
  7.         for (int i=0;i<arraylength;i++)
  8.                 ATLENSURE_SUCCEEDED(out_array.SetAt(i,CComBSTR(in_array[i])));
  9.         CComVariant ccv(out_array.Detach());
  10.         HRESULT hr = ccv.Detach(out_variant);
  11.         ATLENSURE_SUCCEEDED(hr);
  12. }
  13.  
  14. STDMETHODIMP CCalculation::get_output_shortnames(VARIANT* names)
  15. {
  16.         char** names_array = calc_get_short_output_names(calc);
  17.  
  18.         //output_length was set correctly in init() method of CCalculation
  19.         string_array_to_bstr_safearray_variant(output_length,names_array,names);
  20.         return S_OK;
  21. }
  22.  
Code - Auto/Visual Lisp: [Select]
  1. (setq calculation (vlax-create-object "mycomwrapper.Calculation"))
  2. (vlax-invoke-method calculation 'init)
  3. (vlax-invoke-method calculation 'get_output_shortnames 'shortnames) ;shortnames is not initialized first; I think that's how it works
  4. (princ (vlax-safearray->list shortnames))  
  5.  

Daniel Eiszele

  • Newt
  • Posts: 85
Re: COM support broken in Autocad 2012/2013?
« Reply #1 on: May 10, 2012, 08:33:09 AM »
It doesn't help your case, but I had an identical issue with bricscad which just remedied itself with the latest release. For what it's worth your lisp looks good and assuming it was working before upgrading I would think autocad has broken the code :( See if you get the same results from vba or interfacing with c#. Good luck

SIDESHOWBOB

  • Guest
Re: COM support broken in Autocad 2012/2013?
« Reply #2 on: June 21, 2012, 09:14:16 AM »
I just found the answer to this, if anyone else gets a similar problem.

The code posted above is quite correct.  What was happening was this, which got executed earlier in the C++:

Code - C++: [Select]
  1.         STDMETHODIMP CCalculation::configure(VARIANT radii) // radii contains a safearray of doubles
  2.         {
  3.                 CComSafeArray<double> radii_sa;
  4.                 radii_sa.Attach(radii.parray);
  5.                 ULONG num_radii = radii_sa.GetCount();
  6.  
  7.                 //unpack radii array into c-style array
  8.                 double *radii_array = new double[num_radii];
  9.                 for (long i=0;i<num_radii;i++)
  10.                         radii_array[i] = radii_sa.GetAt(i);
  11.  
  12.                 //...do something with radii_array...
  13.  
  14.                 delete[] radii_array;
  15.  
  16.                 return S_OK;
  17.         }

Did you spot the deliberate mistake?  COM rules say that radii is owned by the client (autocad) not my dll.  By attaching to it then letting the wrapper go out of scope, I was deallocating the safearray.  Fixed by adding this before the return statement:

Code - C++: [Select]
  1.                 radii_sa.Detach();

The lisp code didn't try to access radii after sending it to the C++, so this is probably why I got away with it in Acad 2011.  2012/2013 must try to access this data for some reason - or clean it up - why knows.  Either way, undefined behaviour, my fault... and if you've got COM problems in 2011/2012 then double check all your C++ code!