Calling Managed Code from C++ Gotcha
04 Apr 2008Here’s an issue I ran into the other day.
IMarkupServices markup = (IMarkupServices)htmlDocument2;
This line of code was embedded in a C# routine. When called from other C# routines, it worked fine. However, when called from a legacy C++ program it raised an InvalidCastException
.
The inner exception of this code reported a COM error of E_NOINTERFACE
. Huh? Clearly the documentation says that IHTMLDocument2 contains a reference to IMarkupServices
. So what’s happening?
The Gotcha is that many COM (aka ActiveX) controls require single threaded apartment mode. In C#, you can force this by adding the STAThreadAttribute
to your entry point as follows:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
In C++, you can’t do this if you’re entry point is not managed. Instead, you’ll need to use a linker switch:
/CLRTHREADATTRIBUTE:STA
Setting the correct apartment model allows the cast to succeed.
Adam Nathan’s blog article “Gotcha with STAThreadAttribute and Managed C++” explains why this linker setting is necessary.