Ok, so I really was chomping at the bit to blog. Now that we've gone beta I can get a lot of things off of my chest. Just too awkward to blog much before the product was announced, you know? In this post I'm going to give a bit of info on how to write a managed dll that interops with unmanaged code. (FYI: I can't really give the explicit details on how to access the Acrylic automation interfaces at this point.
This is going to be in Managed C++ in 2005. I've mentioned before that it blows P/Invoking out of the water. The syntax is radically different than the Managed Extensions for C++ that was in VS.Net and is really remarkably easy to read and use for those who know C#, so be strong! 😉
Making a project managed in C++ is simply a matter of setting the /clr switch, which you can get to in the project properties panel under "Configuration Properties: General: Project Defaults: Common Language Runtime support". There are some variations of this switch that are pretty well documented and I won't go into them here. Our configuration type is "Dynamic Library (.dll)", of course. (This is in the same properties area.)
We include the standard <windows.h> header and windows version pound defines as we need access to the Win32 api in a number of places. Here's a simplified code snippet that shows you how things work:
// You need to include the relevant headers for the interfaces you're trying to hit.
// This would be defined by the App you're trying to interact with.
extern "C" // Or "C++" whatever your application uses
// The application plugin entry point.
// The __declspec(dllexport) specifies that this function should be exported.
// IApplicationPluginHost is defined in the header provided by the app and included above.
__declspec(dllexport) bool PluginEntry(IApplicationPluginHost *hostAPIs);
// Or wherever else you have your windows includes if you do..
__declspec(dllexport) bool PluginEntry(IApplicationPluginHost *hostAPIs)
// Code to check and save the interface passed back from the application.
That's pretty much the sum of it. From there it's using the host api pointer to grab other interfaces and access functions through those interfaces. So something like hostAPIs->SomeFunction(). We do also have a DllMain (which must be unmanaged according to the SDK) to do some thread initialization that is very app specific in our case. (This would be DLL_THREAD_ATTACH and DLL_THREAD_DETACH message processing.)
In case you're curious, putting completely unmanaged code in your /clr app requires a #pragma managed(push, off) statement before said code and a #pragma managed(pop) afterwords.