I try to load a simple DLL compiled with GCC in cygwin into a C#.NET application. The DLL looks like this
#ifndef __FOO_H
#define __FOO_H
#if _WIN32
#define EXPORT extern "C" __declspec(dllexport)
#else //__GNUC__ >= 4
#define EXPORT extern "C" __attribute__((visibility("default")))
#endif
EXPORT int bar();
#endif // __FOO_H
The function bar() just returns 42.
I compiled and linked the DLL with
g++ -shared -o foo.dll foo.cpp
Now I want to load this super simple DLL into a C# WinForms application.
public partial class Form1 : Form
{
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);
public delegate IntPtr Action2();
unsafe public Form1()
{
InitializeComponent();
IntPtr pcygwin = LoadLibrary("cygwin1.dll");
IntPtr pcyginit = GetProcAddress(pcygwin, "cygwin_dll_init");
Action init = (Action)Marshal.GetDelegateForFunctionPointer(pcyginit, typeof(Action));
init();
}
unsafe private void button1_Click(object sender, EventArgs e)
{
IntPtr foo = LoadLibrary("foo.dll"); // CRASH ... sometimes
IntPtr barProc = GetProcAddress(foo, "bar");
Action2 barAction = (Action2)Marshal.GetDelegateForFunctionPointer(barProc, typeof(Action2));
IntPtr inst = barAction();
}
}
Now the strange thing is: sometimes it works and sometimes it doesn't. When it doesn't work it crashes when it loads foo.dll. I run it in debug mode but I don't even get an exception. The debugger just stops as if I stopped it myself!
I also tried to load foo.dll in the same stack frame where I load cygwin1.dll. Same thing!
Any hints why this happens and what I can do to make it work?
Update 1: We use the latest cygwin and Visual Studio 2010.
Update 2: An assumption is that it has to with timing and garbage collection. It seems to me that the time between loading cygwin1.dll and loading foo.dll matters. The shorter the time between the two LoadLibrary calls the more likely it seems to work.
Update 3: If loading foo.dll succeeds the first time it succeeds always during a session. I can click button1 as often as I want.
Note: LoadLibrary("foo.dll") does not simply fail to load foo.dll. That'd be nice. I crashes and the debugger stops working. Not even an exception is thrown. AND it does not crash always. Sometimes it works!