DLL exports, interop and name mangling

It's been a while since I had a need to use platform invoke to access native methods.  When it comes to Interop I've had to use COM Interop much more frequently than platform invoke.

 

However, while trolling the C# fora for questions to answer, I ran across one about platform invoke that looked interesting.  So to answer it I created a test solution, added a Win32 DLL project and a managed C# console app to call the DLL exports via platform invoke.

 

I kept getting the "EntryPointNotFoundException" whenever calling any of the DLL's exported functions.  Running dumpbin /exports test.dll revealed that the functions were being exported.  I assumed that the name mangled form was just an artifact of the way dumpbin displays function names.

 

The name mangled form, which C++ compilers use in part to create the illusion of class functions being part of a single object, is not just a display artifact.  The name mangled form really is the symbol table entry.  It should have clicked when I was able to access the entry point by it's ordinal (e.g., EntryPoint="#3").  Alas, it didn't.

 

The solution is to decorate standalone exported functions with extern "C" ....   Dumpbin will then show the undecorated name in the list of exports.

 

As is so often the case when working in either a new area or an area that I haven't worked in for a while, it takes an effort to see what is right in front of you.  To accept and, more importantly, understand the error messages.  Dumpbin was literally showing me the name of the exported function but I wanted to believe that it was named what I wanted it to be named (the unmangled version).

Interop with 32-bit DLLs on 64-bit Windows

Visual studio 2005 C# projects default to building for the "Any CPU" target.  If you're trying to P/Invoke a method defined in a 32-bit DLL while running on 64-bit windows then this will cause a "BadImageFormatException".  I believe this is because the "run" VS2005 functionality defaults to executing the 64-bit CLR which probably can't read 32-bit DLLs.

 

The solution is to change the target to x86.  Or to build the 32-bit DLL as a 64-bit DLL but I haven't gotten that far yet!

Forms and State

While working on an app with lots of Windows Forms I've been thinking about the best approach for storing the data in a form.

On the web, since http is stateless, the form is implicitly separated from its state. You, or your framework, has to manage state; when a form is submitted its contents are sent from the client to the server, the server marshals this content into some data model, manipulates this data model, then rebuilds the state by creating an entirely new page. This balance of work shifts a little in the AJAX world. Instead of submitting the entire page to the server, the client submits asynchronous requests to the server, the server sends back results then the client updates the page (and, implicitly) the state of the app.

In client apps, such as a Windows Forms app, the form itself can store state. Since processing occurs in one place (the process running on the client's desktop), when the user changes which item is selected in a list this state is stored in the list widget. Despite this, my background from the web has resulted in a tendency to create separate data objects to store state then manually marshal data into and out of the form.

Having been "raised on the web" when Model-Controller-View was all the rage, I find this separation conceptually pleasing. UI changes were more frequent on the web than they are on the desktop so the separation dramatically reduced the amount of work involved in a page redesign. The web, being much more server-centric, also made heavy use of relational databases. Once you've worked out the relational data model then most of the work of designing the corresponding object model was already done.

In some cases the separation has helped. Having separate, non-visual data objects makes it easy to reuse these objects when an offline or batch mode app is needed. More generally, it makes reuse across apps easier since the data can be consumed directly without having to create phantom/hidden windows.

I also find the UI, even in client apps, to be more fluid than the data model. Sometimes it's easier to use radio buttons, sometimes it's easier to use a combobox. Sometimes, based on the user's choices, you want to swap out user controls. When the data model is separate from the UI, it's easier to experiment with different UI designs.

On the other hand, this separation comes with overhead. The overhead of both creating the data model and marshaling data into and out of the UI.

I don't know whether this cost is offset by the increased incidence of reuse and UI flexibility. Being able to reuse a section of data manipulation code, because it's manipulating data not the UI, does save time. Given a project with enough forms this time savings can be non-trivial.