November 18, 2009

I’ve been working on some graphics work using SlimDx. I really like the library but the documentation is sparse in some places

An Adventure in Function Pointers, Delegates, and Calling Conventions

March 12, 2008

I’ve been interfacing a third-party library for a project at work. The third party library is a DLL with a C interface. Now most libraries for Windows usually have  a __stdcall calling conventions and for some reason I assumed that would be case with the C library. I guess it was because the demo application had  not done anything to give a hint otherwise. Since the client component was going to be in .net component, I wrote a nice little C++/CLI wrapper around the unmanaged native library, so that I could easily call it from C#. I decided against using P/Invoke because I don’t like using meta-information in source code to identify implementation of interfaces. In my opinion using P/Invoke client code too dependent on a specific library. That’s a topic for another post.

One of the functions of the library needed a function pointer to a callback function. The prototype of the function was something like this, wrapped with linkage.

extern "C"
    typedef void (*SomeCallbackType)(int, char*, float);
    void SetCallBackInNativeFunction(SomeCallbackType p){/*...*/}

Since I wanted the callback mechanism to hook up to .Net delegates I did something as follows,

using namespace System;
using namespace System::Runtime::InteropServices;

delegate void FooDelegate(int arg1, char* arg2, float arg3);

ref class AClass
    void FooCallback(int arg1, char *arg2, float arg3){/*...*/}

static GCHandle globalGCHandle;

void SetCallback()
    AClass ^theObj = gcnew AClass();
    FooDelegate ^del = gcnew FooDelegate(theObj, &AClass::FooCallback);
    //We want to do this because the callback will be called many times. 
    //and may live through many garbage collection sprees.
    //This would be freed at the end of the program. 
    globalGCHandle = GCHandle::Alloc(del); 

    IntPtr ptr2Func = Marshal::GetFunctionPointerForDelegate(del);



Now every time time I ran my program, it would start up normally, but then mysteriously crash with really exceptions like 0xC00005, 0xC0000013, etc. I recognized these exceptions that indicated access violation and stack corruption exceptions. I turned on exception handlers in the debugger but the debugger refused to catch those exceptions. I was mystified. I thought that the exceptions were happening because the garbage collector was moving around my delegate, which is why  I used the globalGCHandle = GCHandle::Alloc(del). That didn’t help. Turned out the program was crashing because Marshal::GetFunctionPointerForDelegate returns a function pointer with __stdcall calling convention. Now as everyone knows __stdcall and __cdecl (the default in C compilers) are incompatible, and it causes really confusing errors because the somehow or the other the stack always ends up corrupted. The compiler (at least VC compiler) would have helped had I been passing a native function pointer. With managed code, the compiler happily let me shoot myself in the foot. The solution was to add the following attribute to delegate declaration

delegate void FooDelegate(int arg1, char* arg2, float arg3);

which I got from here

The program worked flawlessly after that (I mean it did what I wanted it to do).


C# Training: Days 2 & 3

March 21, 2007

So I ‘m at the midpoint of the training. Day 2 was interesting where we learned about classes and objects, and there was some discussion of OO techniques. The one feature I really like about Visual Studio 2005 is the Object test bench. Now that is something I can really use at work.

Day 3 was about Collections, generics, Winforms, and ADO.Net. Of these the only thing that I fould interesting was generics. I actually went through the entire excercise and lab. I really like the way generics have been integrated with C# and the way the IDE is aware of them. In contrast, the Visual C++ compiler gives some of the most cryptic error messages when it comes to templates. But then templates are far more powerful than generics. I think by limiting generics for their role in collections and not expanding them to meta-programming like in C++, their use will become easier.

If I had been the one organizing this training, I would’nt have gone around doing it the way it has been done. I would have provided everyone of the developers the new Visual Studio environment, and given each of them a good C# book. I would have told them that they had exactly two weeks to learn the basics of the language. The real traing would have covered topics along the lines of

  • Framework design
  • UI Components/Controls design and implementation
  • Interop
  • Use of C++/CLI to write mix-mode applications and components. This is important because most of our code is in C++/MFC circa 1998.

I think it was pretty condescending of the organizer of the training to think that we needed help in learning how to write classes and objects, when we could have learnt about it on our own.