GlowCode Success Story

I use GlowCode for profiling ObjectARX applications. As far as I know, this is the only profiler that works with AutoCAD. What makes GlowCode special is that it can instrument code on the fly, including a monster like AutoCAD. It has a clunky interface that takes some patience to figure out, but it’s a lifesaver when you need it. ...

June 12, 2010 · 2 min · Owen Wengerd

Visual Studio 2010 Ships

Visual Studio 2010 shipped today accompanied by .NET Framework 4.0. I blogged before about the switch to using the MSBuild build system, and how that theoretically could be helpful in targeting multiple AutoCAD versions from the same solution. The shipping VS 2010 does not support non-Unicode response files, so out-of-the-box it cannot target VC 7.0 (for AutoCAD 2006 and earlier). When time permits, I’m planning to see if I can find a workaround; in the meantime, I’ll continue to use VS 2008 for ObjectARX.

April 12, 2010 · 1 min · Owen Wengerd

AutoCAD for Mac

There have been rumblings and rumors for a while now about a native Mac OS X port of AutoCAD. The ObjectARX 2011 SDK header files contain clear evidence of a native Mac port in the works. The evidence comes in the form of code comments and changes made to the files so that they work with the GCC compiler and the Mac OS X libraries. ...

April 10, 2010 · 2 min · Owen Wengerd

Port Your ObjectARX Code to 64 Bit

AutoCAD versions since AutoCAD 2008 (and since AutoCAD LT 2009) have included both 32 bit and 64 bit flavors on the same media. If you install on a 64 bit Windows system, you get the 64 bit AutoCAD; otherwise you get the 32 bit AutoCAD. The 64 bit AutoCAD can take advantage of as much memory as you can throw at it, whereas the 32 bit version is limited to 2 GB (3 GB if you cheat). They should be otherwise identical in theory, but in practice there are major differences. One big difference is VBA. Microsoft put VBA out to pasture many years ago when they introduced the .NET framework, so there will never be a 64 bit version of VBA. Autodesk had to resort to a seriously inefficient kludge to get it to work at all in the 64 bit flavor of AutoCAD (VBA has to run in a separate 32 bit process, which makes typical applications two orders of magnitude slower). The other big difference is that any third party ObjectARX applications must be installed for the correct architecture. A 32 bit ObjectARX application will not work in a 64 bit AutoCAD. [Note that .NET (or “managed”) applications typically work fine in both architectures – I’m referring to native C++ ObjectARX applications only.] On the Autodesk discussion groups, many people ask how they can install the 32 bit version of AutoCAD on their new 64 bit operating system. Why would they want to do that? Almost always because they need to use an application that is only available for 32 bit AutoCAD architectures, or because they discover that their VBA applications become unbearably slow. It is possible, with some hacking of the AutoCAD installation database, to install the 32 bit flavor of AutoCAD on a 64 bit system, but I don’t recommend that. There is just no excuse any more to not support the 64 bit architecture. If you find yourself in this situation, put pressure on the developer of the application to get it ported. In fact, if you rely on an application that hasn’t been ported to the 64 bit architecture, I’d like to hear from you. Add a comment to this post and let me know the name of the application. If you are a vendor or developer that has not yet ported your 32 bit application, please contact me – I will gladly port it for you. Even large applications can typically be ported in several hours. BTW, I am well aware that even Autodesk is guilty of not supporting 64 bit platforms in some of its vertical market AutoCAD versions (and corresponding object enablers). I certainly hope they remedy that situation in the next release cycle.

March 11, 2010 · 3 min · Owen Wengerd

Visual Studio 2010 and VC Build Hook

[Update: See Visual Studio 2010 Native Multi-Targeting] Many of you use my VC Build Hook utility to target multiple versions of AutoCAD from a single solution in Visual Studio 2008. Visual Studio 2010 now includes a new feature called native multi-targeting that performs the same function as VC Build Hook. The new feature works great for using build tools back to VC 7.1, but it does not work with VC 7, which is required for targeting AutoCAD versions 2006 and earlier. ...

January 11, 2010 · 1 min · Owen Wengerd

Automatic LISP Loading

There are a myriad of ways to load AutoLISP applications in AutoCAD, including acaddoc.lsp, an .mnl file, the Startup Suite, and manually by various means. For application developers wishing to deploy their applications to others, all of these methods have drawbacks. The ideal solution should be easy to implement in an installation program, require minimal or zero changes to the user’s AutoCAD configuration, work the same way across all versions of AutoCAD, and easily undone when the application is uninstalled. ...

December 24, 2009 · 3 min · Owen Wengerd

ArxDbg Utility

ArxDbg is the name of a sample project that has been included with the ObjectARX SDK for many years. It’s primary purpose is to demonstrate how to use the ObjectARX API, but it is a complete free-standing utility in its own right. ObjectARX programmers often use this utility during development for testing and exercising their application code, but it can be useful to anybody, not just programmers. ...

September 23, 2009 · 1 min · Owen Wengerd

Disable InfoCenter in AutoCAD 2010

[Update: See Disable AutoCAD InfoCenter] In case you missed it, Tony Tanzillo has posted instructions for disabling the InfoCenter in AutoCAD 2010. AutoCAD 2010 starts faster when the InfoCenter is disabled. To make it easy, I’ve created an AutoLISP file that defines commands named DisableInfoCenter and EnableInfoCenter: ...

March 30, 2009 · 1 min · Owen Wengerd

ObjectARX 2010: Dealing With Missing Exports

In the new ObjectARX 2010 SDK, Autodesk has added some new virtual member functions that are not exported as they should be. For example, the AcGiFaceData class has had two new virtual functions added for setting and getting the face transparency: class AcGiFaceData: public AcRxObject { //[… deleted for brevity] ACDB_PORT virtual AcDbObjectId materials() const; ACDB_PORT virtual AcGiMapper mappers() const virtual void setTransparency(const AcCmTransparency transparency); virtual AcCmTransparency transparency() const private: AcGiImpFaceData mpAcGiImpFaceData; }; As you can see, whoever added the new functions neglected to prefix them with the ACDB_PORT macro. ACDB_PORT evaluates to __declspec(export), which tells the compiler to export the function. Since the macro is missing, the new functions are not exported from acdb18.dll. Since these are virtual functions, you won’t have any problems calling them through a pointer to an AcGiFaceData object that was constructed by AutoCAD. The problem arises when you derive a class from AcGiFaceData. Since the functions are not exported, the linker has no way of resolving their address for creating the virtual function table of your derived class. This results in linker errors: acrxEntryPoint.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall AcGiFaceData::setTransparency(class AcCmTransparency const )” (?setTransparency@AcGiFaceData@@UAEXPBVAcCmTransparency@@@Z) acrxEntryPoint.obj : error LNK2001: unresolved external symbol “public: virtual class AcCmTransparency * __thiscall AcGiFaceData::transparency(void)const " (?transparency@AcGiFaceData@@UBEPAVAcCmTransparency@@XZ)Following is an example that results in these errors: class AcGiFaceDataEx: public AcGiFaceData { public: AcGiFaceDataEx() {} ~AcGiFaceDataEx() {} } Test; The only solution is to provide an implementation of the missing functions. In this case, it could be accomplished by something like this: class AcGiFaceDataEx: public AcGiFaceData { AcCmTransparency mpTransparency; public: AcGiFaceDataEx() : mpTransparency( NULL ) {} ~AcGiFaceDataEx() { delete mpTransparency; } virtual void setTransparency(const AcCmTransparency transparency) { delete mpTransparency; mpTransparency = (transparency? new AcCmTransparency( transparency ) : NULL); } virtual AcCmTransparency transparency() const { return mpTransparency; } } Test;This will fix the linker errors, but there is no guarantee that it will work as intended. AutoCAD might access its internal transparency value directly without calling through the member functions, which means it would never “see” the transparency set through the replacement member functions. Furthermore, the addition of the new pointer member changes the size of the class, which causes AcGiFaceDataEx arrays to have a different memory footprint than AcGiFaceData arrays. Lastly, what if Autodesk fixes the problem in a future AutoCAD service pack? The ideal solution should not change the size of the class. It should check at runtime whether the function is exported, then use the exported function if it exists. That way, code that is written now will use the exported function if and when it becomes available in a future version of AutoCAD. When the function is not exported, an alternate implementation must be provided. This is not an unusual scenario, and the solution I present for the specific case of AcGiFaceData can be adapted to the more general problem. In the AcGiFaceData case, the missing functions are virtual functions. Knowing this, it is possible to use a trick to get the address of the real function. In the code below, the function getAcGiFaceData_vtable() constructs a temporary AcGiFaceData object, from which it extracts a pointer to the object’s virtual function table. The virtual function table is just an array of function pointers, so the address of the desired function can be obtained by indexing into the virtual function table. The question is, how far? By counting virtual functions and data members starting from the top of the class hierarchy: in this case, 6 virtual functions in AcRxObject plus 16 virtual functions in AcGiFaceData = 22. Note that obtaining a function pointer this way relies on Visual C++ implementation details, but this is safe to do since all ObjectARX modules must be compiled in Visual C++. Following is my solution to the missing AcGiFaceData functions: #pragma warning(push) #pragma warning(disable: 4608) template < typename Src, typename Dest > Dest force_cast( Src src ) { union _convertor { Dest d; Src s; _convertor() : d(0), s(0) {} } convertor; convertor.s = src; return convertor.d; } #pragma warning(pop) static FARPROC getAcGiFaceData_vtable() { static FARPROC rfVTable = (FARPROC**)&AcGiFaceData(); return (rfVTable? rfVTable : NULL); } void AcGiFaceData::setTransparency( const AcCmTransparency transparency ) { typedef void (AcGiFaceData::F_setTransparency)( const AcCmTransparency ); static F_setTransparency pfSetTransparency = force_cast< FARPROC, F_setTransparency >(GetProcAddress( GetModuleHandleA( “acdb18.dll”), “?setTransparency@AcGiFaceData@@UEAAXPEBVAcCmTransparency@@@Z” )); if( !pfSetTransparency ) { static FARPROC rfVTable = getAcGiFaceData_vtable(); if( rfVTable ) pfSetTransparency = force_cast< FARPROC, F_setTransparency >( rfVTable[22] ); } if( pfSetTransparency ) (this->pfSetTransparency)( transparency ); } AcCmTransparency AcGiFaceData::transparency() const { typedef AcCmTransparency (AcGiFaceData::F_transparency)() const; static F_transparency pfTransparency = force_cast< FARPROC, F_transparency >(GetProcAddress( GetModuleHandleA( “acdb18.dll”), “?transparency@AcGiFaceData@@UEBAPEAVAcCmTransparency@@XZ” )); if( !pfTransparency ) { static FARPROC rfVTable = getAcGiFaceData_vtable(); if( rfVTable ) pfTransparency = force_cast< FARPROC, F_transparency >( rfVTable[23] ); } if( pfTransparency ) return (this->*pfTransparency)(); return NULL; }

March 28, 2009 · 4 min · Owen Wengerd

Missing Menu Madness

One of my many complaints about about the CUI system introduced in AutoCAD 2006 is that it's not very friendly to third party developers. In my opinion, it's not very friendly to end users either, but I digress... One example of the unfriendly CUI is the case where a third party application installs a partial menu. In the pre-CUI days, adding a partial menu was an easy way to add an application specific menu to AutoCAD without making any changes to the end user's existing menu files. If the application was later uninstalled, the uninstall script could remove its menu and clean up the registry, leaving no trace behind. CUI breaks that scenario. ...

December 22, 2008 · 2 min · Owen Wengerd

Debugging ObjectARX: Break on Exception

I have presented a class entitled High Octane ObjectARX at Autodesk University the past two years. In 2006 the focus was on project organization, and last year I focused more on techniques for supporting multiple versions of AutoCAD with a single Visual Studio solution, touching briefly on testing and profiling. For 2008 I plan to focus on debugging. ...

May 12, 2008 · 2 min · Owen Wengerd

Hotel Autodesk

Steve Johnson asks “where have all the developers gone?”, and Deelip Menezes wonders in a comment whether Autodesk’s annual release cycle for AutoCAD is part of the problem. I’ve always said that an annual release cycle is untenable. The annual release cycle is motivated by Autodesk’s desire to make the subscription program look attractive. Has it worked? Based on what I’ve read and heard through the grapevine, it has definitely worked. More customers than ever are choosing the subscription model. In many cases, the annual subscription business model actually works well for software like AutoCAD, providing benefits for both Autodesk and their customers. But subscription is not for everyone. In typical greedy big corporate fashion, Autodesk have overplayed their hand. Instead of concentrating on those customers for whom subscription makes sense and leaving the others to choose a different model, the “more is always better” marketing machine kicked in. Ergo, the annual release cycle carrot and the AutoCAD retirement program stick were invented. [Oh sorry, it’s called the Autodesk Loyalty Program.] I am already seeing the beginnings of a movement of discontent among Autodesk customers, and I expect the annual release cycle to collapse under its own weight within another year or two. In the meantime, tremendous damage is being done. Customers, third party developers, authors, and consultants all suffer under the strain of the annual release cycle, but that’s only the tip of the iceberg. To pull off annual releases, Autodesk have to be working on multiple versions of AutoCAD in parallel. While AutoCAD 2006 was being beta tested, AutoCAD 2007 and 2008 were already under development, and AutoCAD 2009 was already in the planning stages. When CUI was first introduced to the public, the new ribbon UI was likely already in the planning stages. Is it any wonder that the angry feedback about CUI was ignored? When you have an annual release cycle with 3 or 4 future releases on parallel tracks, you can’t just stop and fix a fundamental design flaw. All you can do is increase your public relations budget. The harm done to third party developers is substantial, but the inability to shift gears and correct fundamental design flaws is the real travesty of the annual release cycle.

April 30, 2008 · 2 min · Owen Wengerd