我尝试将在 cygwin 中使用 GCC 编译的简单 DLL 加载到 C#.NET 应用程序中。DLL 看起来像这样
#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
函数 bar() 只返回 42。
我编译并链接了 DLL
g++ -shared -o foo.dll foo.cpp
现在我想将这个超级简单的 DLL 加载到 C# WinForms 应用程序中。
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();
}
}
现在奇怪的是:有时它起作用,有时它不起作用。当它不工作时,它会在加载 foo.dll 时崩溃。我在调试模式下运行它,但我什至没有得到异常。调试器就像我自己停止一样停止!
我还尝试在加载 cygwin1.dll 的同一堆栈框架中加载 foo.dll。一样!
任何提示为什么会发生这种情况以及我可以做些什么来使它工作?
更新 1:我们使用最新的 cygwin 和 Visual Studio 2010。
更新 2:假设它必须与时间和垃圾收集有关。在我看来,加载 cygwin1.dll 和加载 foo.dll 之间的时间很重要。两个 LoadLibrary 调用之间的时间越短,它似乎就越有可能起作用。
更新 3:如果加载 foo.dll 第一次成功,它总是在会话期间成功。我可以随心所欲地单击 button1。
注意: LoadLibrary("foo.dll") 不会简单地加载 foo.dll 失败。那会很好。我崩溃了,调试器停止工作。甚至没有抛出异常。而且它并不总是崩溃。有时它有效!