How to call cygwin compiled C++ from .NET Core?

15

I am trying to do something similar to this:

I am working on Windows but my intention is to make my code work on Linux too later on (therefore I work with cygwin and clion for C++ ). VS2017 to compile the C# for a .NET Core app with a normal C# compiler. My problem is getting this error in visual studio:

"The program '[19944] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'."

Here is my cmake file (generated with clion):

cmake_minimum_required(VERSION 3.10) project(callFromCsharp)

set(CMAKE_CXX_STANDARD 14)

add_library(callFromCsharp SHARED library.cpp)

Here is my C++ code in library.cpp:

#include <cstdint>

extern "C" __declspec(dllexport) int32_t Test(){
    return 10;
}

This is my cmake call generated by clion

C:\Users\Daant.CLion2018.1\system\cygwin_cmake\bin\cmake.exe --build /cygdrive/c/Users/Daant/CLionProjects/callFromCsharp/cmake-build-release --target callFromCsharp -- -j 6

Here is my C# code:

    class Program
    {
        [DllImport("cygcallFromCsharp.dll", EntryPoint = "Test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
        public static extern Int32 Test();

        [STAThread]
        static void Main()
        {
            var res = Test();
            Console.WriteLine($"Done! {res}");
            Console.ReadLine();
        }
    }

How to solve this? I just want to call a C++ method without errors or exceptions.

c#
c++
cmake
.net-core
cygwin
asked on Stack Overflow May 31, 2018 by Daan • edited Jun 1, 2018 by Daan

2 Answers

4

Lets begin with what not to do

when loading Cygwin dll from C# (I guess from Visual studio it will be the same).

  1. do not use AnyCPU as platform, prefer to use x64 or x86 platform, in respectively to the Cygwin dll.
  2. for some reason, I didn't figured out yet why, calling sprintf, sscanf ,stringstream ... and prints to console methods from the dll cause the program to halt.

Now What you can do:

  1. Make sure cygwin bin folder added to path, or copy your DLL's dependencies to the DLL's folder (dependencies are usually: Cygwin1.dll, cyggcc_s-seh-1.dll cygstdc++-6.dll. use Dependency Walker tool to check).
  2. Just to make sure: add EXPORT_API macro, use it on each exported method. like:

#define EXPORT_API extern "C" __cdecl __declspec(dllexport)

  1. Your DLL sample is very simple, compile your code using Cygwin console: g++ -c library.cpp; g++ -o cygcallFromCsharp.dll library.o
  2. I used from C# the following (debug running dir set to dll location):

DllImport(@"cygcallFromCsharp.dll", CallingConvention=CallingConvention.Cdecl)] static extern int Test();

Hope it will help.

answered on Stack Overflow Jun 5, 2018 by SHR
1

I implemented a dotnet loader which is compatible with cygwin. You can find it here: https://github.com/smx-smx/EzDotnet

In order to be able to use Cygwin from .NET (without any crashes) the entry point MUST be a Cygwin application, compiled and linked under cygwin.

I added a cygwin sample that demonstrates the use of P/Invoke as well as read(2) and write(2) to redirect the C# stdin/stdout to cygwin (otherwise it wouldn't be visible)

./samples/cli/ezdotnet.exe ./CoreCLR/cygcoreclrhost.dll ./samples/Managed/Cygwin/bin/Debug/net5.0/Cygwin.dll ManagedSample.EntryPoint Entry

answered on Stack Overflow Jan 2, 2021 by Smx

User contributions licensed under CC BY-SA 3.0