1

I want to load some C++ dlls compiled in Cygwin to my C# project (4.7.1 or Standard 2.0), and the first step is to load cygwin1.dll, of course. But I've stuck at this step. As suggested here I've tried something like:

[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
}

but no luck. The app simply crashes and VS output shows "Access violation" error. It happens at the last line (init();).

Then I tried the same in simple C++ console app (found at the same page referenced above):

#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();
}

And it works great. Then I've decided to create a simple C++ DLL in Visual Studio, which will wrap all cygwin access, and then load this new DLL in my C# project, so I've created something like:

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;
}

I've also created a def file that exports the function and loaded the new dll into my C# project. But again I've got access violation crash when cygwin_dll_init() is reached. Weird thing is that the same exact C++ dll works great if it's called from another C++ console app. But when called from .NET console app - it crashes.

Another thing that I've tried is to increase stack memory limit (I've read somewhere that it may be the reason...), so I've created the following thread:

var thread = new Thread(Runner, int.MaxValue);// maxStackSize = int.MaxValue
thread.Start();

And I've moved all my code in Runner method executed by the thread. This time the app doesn't crash, but the thread crashes when cygwin_dll_init() is reached.

Any suggestions?

Thanks!

UPDATE: I've just tried with C++/CLI wrapper, but no luck. The same access violation error strikes again...

UPDATE 2: I've just discovered that, if I use 32bit version of cygwin1.dll, and compile my C# project for x86 architecture - everything works! But if I use 64bit version of cygwin1.dll, and compile my C# project for x64 architecture - I'm getting access violation error. The first thing that came through my mind is that file system redirection somehow confuses cygwin1.dll, but it looks that it isn't the case (I've tried with Wow64DisableWow64FsRedirection). One step closer, but still don't have the solution...

Aleksandar Pesic
  • 668
  • 7
  • 18
  • Instead for compiling the C++ DLLs for the cygwin environment, consider cross-compiling for the mingw64 environment. There is a cygwin package that provides the mingw64 cross-compiler. When run (in cygwin) it creates DLLs which do not use cygwin1.dll. Such DLLs work better within the Windows environment as they do not require the cygwin1.dll (so you don't have to initialize that). You may still need to link in some of the mingw64 runtime DLLs (again provided in the cross-compiler package, but also not requiring cygwin1.dll). – Doug Henderson Dec 08 '19 at 04:44
  • Thanks for tryng to help! I don't have experience with cross compiling, but I doubt that I can avoid having cygwin1.dll dependency because my program needs to use some functions which live there (i.e. `forkpty`). Please correct me if I'm wrong. Thanks! – Aleksandar Pesic Dec 09 '19 at 10:21
  • I have the same problem. No solution yet. – Ladislav Aug 29 '21 at 18:11
  • I suspect that cygwin1.dll may not be able to live in a process with the .NET runtime, based on this: https://github.com/Alexpux/Cygwin/blob/master/winsup/cygwin/how-cygtls-works.txt "If you load cygwin1.dll dynamically from a non-cygwin application, it is vital that the bottom CYGTLS_PADSIZE bytes of the stack are not in use before you call cygwin_dll_init()." – Cyanfish Sep 04 '22 at 18:58

0 Answers0