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 th开发者_运维百科e 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!
Look at the "UPDATED" part of my old answer about the close problem. I recommend you to to compile your DLL with respect of MinGW tools instead of CygWin tools. If nothing is changed in the since the time the requirement "Make sure you have 4K of scratch space at the bottom of your stack" makes CygWin DLLs incompatible to .NET. I don't know how to realized the requirement in a .NET application.
You should try process monitor from msft. This is most likely being caused by a failure to load a dependent dll. Process monitor will show you what dll and why it is not loading.
Try the following...
[DllImport("kernel32", CharSet=CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpLibFileName);
maybe even use
[DllImport("kernel32", CharSet=CharSet.Unicode, SetLastError=true)]
and check for return values from both your calls to LoadLibrary and GetProcAddress before trying to use them.
精彩评论