*** 关于从 C# 调用本机 C++

Posted

技术标签:

【中文标题】*** 关于从 C# 调用本机 C++【英文标题】:*** on calling native c++ from c# 【发布时间】:2015-01-29 13:59:28 【问题描述】:

我正在尝试从 C# 项目调用本机 C++ 代码。为此,我按照this post 中的步骤操作。

但是当我在 C++ 文件中创建一个巨大的数组时,我得到了一个 *** 异常。代码如下:

//CSharpTest.h

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpTest

    class Program
    
        static void Main(string[] args)
        
            CpTest.Class1 instance = new CpTest.Class1();
            Console.WriteLine(instance.DoSomething());
            Console.ReadKey();
        
    

还有 c++ 文件

// CpTest.h

#pragma once

using namespace System;

namespace CpTest 

    public ref class Class1
    
    public:
        int DoSomething()
            int arr[640 * 480];
            return 123;
        
        // TODO: Add your methods for this class here.
    ;

数组声明导致***异常。

早些时候,当我只运行本机 C++ 代码时,我通过增加项目属性中的“堆栈保留大小”来增加堆栈大小。

但对于这种情况,我不知道该怎么办。

【问题讨论】:

必须在栈上分配数组吗? 不一定。但我不知道该怎么做。 您的“本机 C++”实际上是 C++/CLI,即 Microsoft 针对 .Net 互操作的 C++ 扩展。我已经删除了 C++ 标签并添加了 c++-cli。 在堆上分配数组,或者最好使用std::vector。在堆栈上分配如此大的数组通常不是一个好主意。 @odyss-jii 感谢您的帮助 【参考方案1】:
  int arr[640 * 480];

此数组存储在 C 或 C++ 程序的堆栈中。相当于 C# 程序中的 stackalloc。它需要 640 x 480 x 4 = 1,228,800 字节的存储空间。太多了,堆栈的默认大小是 1 兆字节。你溢出了堆栈,异常告诉你。

这是本机代码中的一个缺陷,它不应该依赖如此大的分配来在运行时实现,而应该使用免费存储。运算符 new 在 C++ 程序中,malloc 在 C 程序中。

在 C++/CLI 程序中最好是 array<int>^,这是一个存储在 GC 堆上的托管数组,就像 C# 数组一样。你可以使用 pin_ptr 来允许原生代码在阵列上参与。

从技术上讲,它可以在 C# 项目中修复,您必须为启动线程请求更大的堆栈,即操作系统创建并调用您的 Main() 方法的堆栈。当您以 x64 为目标时,您会自动获得一个,默认值为 4 兆字节。但是,如果您必须与现有的本机代码互操作,这通常不是一个选择。您可以使用 /STACK 选项运行 Editbin.exe 来修补 EXE 文件头并要求更大的堆栈。 C# 项目中的构建后事件可能如下所示:

  set path=%path%;$(DevEnvDir);$(DevEnvDir)..\..\vc\bin
  editbin.exe /STACK:2097152 "$(TargetPath)"

或从您自己创建的线程运行本机代码,使用可让您指定堆栈大小的Thread constructors 之一。

【讨论】:

以上是关于*** 关于从 C# 调用本机 C++的主要内容,如果未能解决你的问题,请参考以下文章

从 c# 代码调用带有 void *parameter 的本机 c++ 函数

通过 Marshal.GetFunctionPointerForDelegate 从本机 (C++) 线程调用托管函数 (C#)

从本机 C++ 调用 C#,而不使用 /clr 或 COM?

如何从 C# 调用 C++ 类

未导出成员函数时,从 C# 调用 C++ 本机/非托管成员函数

如何附加调试器以从托管(C#)包装器进入本机(C++)代码?