我想将在Cygwin中编译的一些C ++ dll加载到我的C#项目(4.7.1或Standard 2.0)中,当然,第一步是加载cygwin1.dll
。但是我坚持这一步。按照建议的here,我尝试过类似的操作:
[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);
static void Main(string[] args)
{
IntPtr pcygwin = Loadlibrary("cygwin1.dll");
IntPtr pcyginit = GetProcAddress(pcygwin,"cygwin_dll_init");
action init = (action)Marshal.GetDelegateForFunctionPointer(pcyginit,typeof(action));
init();// Here the error happens
}
但是没有运气。该应用程序仅崩溃,VS输出显示“访问冲突”错误。它发生在最后一行(init();
)。
然后,我在简单的C ++控制台应用程序中尝试了相同的操作(在上面引用的同一页中找到):
#include <windows.h>
typedef void (*PFN_CYGWIN_DLL_INIT)();
int main()
{
HMODULE h = Loadlibrary(TEXT("cygwin1.dll"));
PFN_CYGWIN_DLL_INIT init = (PFN_CYGWIN_DLL_INIT) GetProcAddress(h,"cygwin_dll_init");
init();
}
效果很好。然后,我决定在Visual Studio中创建一个简单的C ++ DLL,它将包装所有cygwin访问,然后将这个新的DLL加载到我的C#项目中,所以我创建了类似的东西:
typedef void (*an_action)();
HMODULE h_cygwin;
bool initialize()
{
h_cygwin = Loadlibrary(TEXT("cygwin1.dll"));
if (h_cygwin == nullptr)
return false;
auto cygwin_dll_init = (an_action) GetProcAddress(h_cygwin,"cygwin_dll_init");
if (cygwin_dll_init == nullptr)
return false;
cygwin_dll_init();
return true;
}
我还创建了一个def文件,该文件导出函数并将新的dll加载到我的C#项目中。但是当到达cygwin_dll_init()
时,我又遇到了访问冲突崩溃。奇怪的是,如果从另一个C ++控制台应用程序调用它,那么相同的C ++ dll会很好地工作。但是,当从.NET控制台应用程序调用时,它会崩溃。
我尝试过的另一件事是增加堆栈内存限制(我读过某处可能是原因...),所以我创建了以下线程:
var thread = new Thread(Runner,int.MaxValue);// maxStackSize = int.MaxValue
thread.Start();
并且我已经将所有代码移至该线程执行的Runner
方法中。这次应用程序不会崩溃,但是到达cygwin_dll_init()
时线程崩溃。
有什么建议吗?
谢谢!
更新:我刚刚尝试过使用C ++ / CLI包装器,但是没有运气。再次出现相同的访问冲突错误...
更新2:我刚刚发现,如果我使用32位版本的cygwin1.dll
,并为x86体系结构编译我的C#项目-一切正常!但是,如果我使用cygwin1.dll
的64位版本,并为x64体系结构编译我的C#项目-我会遇到访问冲突错误。我想到的第一件事是文件系统重定向以某种方式使cygwin1.dll感到困惑,但事实并非如此(我尝试使用Wow64DisableWow64FsRedirection
)。离我们更近了一步,但仍然没有解决方案...