You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从.NET Core调用Cygwin编译的C++?解决0xc0000005访问违例

解决C#调用Cygwin编译的C++ DLL时的访问违例问题

首先,你的问题核心在于Cygwin编译的DLL并非Windows原生共享库——它依赖Cygwin的POSIX兼容层(cygwin1.dll),而.NET Core在Windows上是原生Win32程序,直接调用这类DLL会因为环境未初始化或依赖缺失导致访问违例(错误码0xc0000005)。下面给你两种解决方案,优先推荐第一种,更适配跨平台需求:

方案一:改用MinGW-w64编译原生Windows DLL(推荐)

MinGW-w64可以编译不依赖POSIX层的原生Windows DLL,同时和Linux下的GCC编译流程兼容,完美契合你跨平台的需求。

步骤:

  1. 切换CLion工具链为MinGW-w64
    在CLion的Settings → Build, Execution, Deployment → Toolchains中,添加MinGW-w64工具链(确保下载对应你系统架构的版本,x64或x86)。
  2. 调整CMake配置
    保留你的基础CMakeLists.txt,可额外添加一行确保导出符号正确:
    cmake_minimum_required(VERSION 3.10)
    project(callFromCsharp)
    set(CMAKE_CXX_STANDARD 14)
    add_library(callFromCsharp SHARED library.cpp)
    # 自动导出所有符号,避免MinGW的命名修饰问题
    set_target_properties(callFromCsharp PROPERTIES
        WINDOWS_EXPORT_ALL_SYMBOLS ON
    )
    
  3. 保持C++代码不变
    你的extern "C" __declspec(dllexport)已经能正确导出C风格函数,无需修改:
    #include <cstdint>
    extern "C" __declspec(dllexport) int32_t Test(){
        return 10;
    }
    
  4. 修改C#的DllImport配置
    MinGW编译出的DLL没有cyg前缀,直接使用库名即可:
    class Program
    {
        [DllImport("callFromCsharp.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();
        }
    }
    
  5. 部署DLL
    将编译生成的callFromCsharp.dll复制到C#程序的输出目录(比如bin/Debug/netcoreapp3.1),运行程序即可正常调用。

方案二:继续使用Cygwin,但修复依赖和环境初始化

如果你坚持用Cygwin编译,需要解决两个关键问题:

步骤:

  1. 添加Cygwin运行时依赖
    找到Cygwin安装目录下的cygwin1.dll(通常在C:\cygwin64\bin),将其复制到C#程序的输出目录,或者把Cygwin的bin目录添加到系统PATH中。
  2. 初始化Cygwin环境
    Cygwin的DLL需要先初始化POSIX环境才能正常工作,修改你的C++代码添加初始化函数:
    #include <cstdint>
    #include <cygwin/cygwin_dll.h>
    
    extern "C" __declspec(dllexport) void InitCygwin() {
        cygwin_dll_init(); // 初始化Cygwin环境
    }
    
    extern "C" __declspec(dllexport) int32_t Test(){
        return 10;
    }
    
  3. 修改C#代码先调用初始化函数
    class Program
    {
        [DllImport("cygcallFromCsharp.dll", EntryPoint = "InitCygwin", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
        public static extern void InitCygwin();
    
        [DllImport("cygcallFromCsharp.dll", EntryPoint = "Test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
        public static extern Int32 Test();
    
        [STAThread]
        static void Main()
        {
            InitCygwin(); // 必须先初始化
            var res = Test();
            Console.WriteLine($"Done! {res}");
            Console.ReadLine();
        }
    }
    

额外注意事项

  • 架构匹配:确保C++编译的DLL和C#程序的架构一致(都是x64或都是x86),CLion工具链和VS的目标平台要对应。
  • 跨平台兼容:Linux下直接用GCC编译共享库(.so文件),C#的DllImport可以通过条件编译区分平台:
    #if WINDOWS
    [DllImport("callFromCsharp.dll", ...)]
    #elif LINUX
    [DllImport("libcallFromCsharp.so", ...)]
    #endif
    

内容的提问来源于stack exchange,提问作者Daan

火山引擎 最新活动