C++/CLI 委托作为函数指针 (System.AccessViolationException)

2023-12-30

我一直在尝试使用 C++/CLI 委托(因为我正在尝试创建 .NET 参考库),并且遇到了以下问题。

我在 C++/CLI 中定义一个委托,然后在 C# 中创建该委托的实例,然后通过函数指针通过非托管 C++ 调用该委托的实例。这一切都按预期进行。

说明这一点的代码(首先是我的 C#)

using System;

namespace TestProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
            Library.Test test = new Library.Test(messageDelegate);
            test.WriteMessage();
            Console.Read();
        }

        static void Message()
        {
            Console.WriteLine(1024);
        }
    }
}

接下来是我的托管 C++ 文件 (Managed.cpp)

#include "Unmanaged.hpp"
#include <string>

namespace Library
{
    using namespace System;
    using namespace System::Runtime::InteropServices;

    public ref class Test
    {
    public:
        delegate void MessageDelegate();
    internal:
        MessageDelegate^ Message;
        void* delegatePointer;

    public:
        Test(MessageDelegate^ messageDelegate)
        {
            delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
        }

        void WriteMessage()
        {
            Unmanaged::WriteMessage(delegatePointer);
        }
    };
}

和我的非托管 C++ 文件 (Unmanagement.cpp)

#include "Unmanaged.hpp"

namespace Unmanaged
{
    typedef void (*WriteMessageType)();
    WriteMessageType WriteMessageFunc;

    void WriteMessage(void* Function)
    {
        WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
        WriteMessageFunc();
    }
}

此代码全部按预期工作,输出为“1024”,因为 Method() 是由指向委托方法的函数指针调用的。

当尝试对带有参数的委托应用相同的方法时,出现了我的问题,即:

delegate void MessageDelegate(int number);

我的代码现在如下(C#):

using System;

namespace AddProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
            Library.Test test = new Library.Test(messageDelegate);
            test.WriteMessage(1024);
            Console.Read();
        }

        static void Message(int number)
        {
            Console.WriteLine(number);
        }
    }
}

我的托管 C++ 文件:

#include "Unmanaged.hpp"
#include <string>

namespace Library
{
    using namespace System;
    using namespace System::Runtime::InteropServices;

    public ref class Test
    {
    public:
        delegate void MessageDelegate(int number);
    internal:
        MessageDelegate^ Message;
        void* delegatePointer;

    public:
        Test(MessageDelegate^ messageDelegate)
        {
            delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
        }

        void WriteMessage(int number)
        {
            Unmanaged::WriteMessage(delegatePointer, number);
        }
    };
}

我的非托管 C++ 文件:

#include "Unmanaged.hpp"

namespace Unmanaged
{
    typedef void (*WriteMessageType)(int number);
    WriteMessageType WriteMessageFunc;

    void WriteMessage(void* Function, int number)
    {
        WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
        WriteMessageFunc(number);
    }
}

当我执行该程序时,出现以下错误:

“System.AccessViolationException”类型的未处理异常 发生在非托管库 Test.dll 中

附加信息:尝试读取或写入受保护的内存。 这通常表明其他内存已损坏。

顺便说一句,控制台窗口确实显示 1024,但后面跟着一个随机 int (~1000000),然后我收到错误。

我可以开始想象出现此错误的一些原因,但我不确定并且很难找出。如果有人能告诉我为什么会出现此错误,以及我可以采取哪些措施来解决它,我将不胜感激。


 void WriteMessage(void* Function, int number)

将函数指针作为 void* 传递是一个非常糟糕的主意。它可以防止编译器检查您是否做错了什么。尽管编译器在这种特定情况下无法检测到它,但还是有问题。委托被编组为使用 __stdcall 调用约定的函数指针,实际函数指针使用 __cdecl 调用约定(本机代码的默认设置)。这会导致堆栈在调用时变得不平衡。

您可以通过应用来修复它[非托管函数指针] 属性 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedfunctionpointerattribute%28v=VS.90%29.aspx在委托声明中指定 CallingConvention::Cdecl。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++/CLI 委托作为函数指针 (System.AccessViolationException) 的相关文章

  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • 页面中某些超链接控件上的本地化资源未发生变化

    上面是正在开发中的网站的屏幕截图 我们有一个 DropdownList 控件 并在其 SelectedIndexChanged 上进行回发 然后我们更改站点区域性 然后加载相应的资源文件 DropDownList ASP NET 代码
  • MS Source Server - 使用 srctool 查看时源流显然不存在

    我一直在尝试安装 MS 调试工具中的 MS Source Server 内容 目前 我正在通过 Subversion 索引命令运行我的代码 pdbs 该命令现在按预期运行 它为给定的 pdb 文件创建流并将其写入 pdb 文件 但是 当我在
  • LINQ to Entities 区分大小写的比较

    这不是 LINQ to Entities 中区分大小写的比较 Thingies First t gt t Name ThingamaBob 如何使用 LINQ to Entities 实现区分大小写的比较 那是因为你正在使用LINQ 实体最
  • 何时使用 Windows Workflow Foundation? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有些事情仅通过手动 代码 更容易实现 但有些事情通过 WF 更容易实现 看起来 WF 可以用来创建 几乎 任何类型的算法 所以 理论上 我可以在
  • 在 Visual Studio C++ 2008 中包含 dll

    有没有办法将 dll 包含在项目中 这样我就不必在编译后将这些 dll 与可执行文件放在同一文件夹中 这样我就可以用它们编译我的项目 这是否有可能 如果是 有人可以指导我 我的项目是一个 opencv 项目 有很多 dll 我必须包含在文件
  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • WCF服务健康状况监控

    我刚刚实现了 WCF 服务 目前正在研究服务监控选项 我们的服务器团队目前仅托管 java 服务 希望我们的实例始终运行 因此它可以在该实例的生命周期内收集数据 他们表示将使用我们的 webmon 操作之一来获取统计信息 但我们正在使用每次
  • 如何使正则表达式匹配不区分大小写?

    我有以下正则表达式加拿大的邮政编码 http en wikipedia org wiki Postal codes in Canada ABCEGHJKLMNPRSTVXY 1 d 1 A Z 1 d 1 A Z 1 d 1 它工作正常 但
  • 如何将 Razor 视图转换为字符串?

    我想使用我的 Razor 视图作为某种发送电子邮件的模板 所以我想将我的模板 保存 在视图中 将其作为字符串读入控制器 进行一些必要的替换 然后发送它 我有有效的解决方案 我的模板作为 HTML 页面托管在某处 但我想将其放入我的应用程序中
  • 访问 XAML 中的静态字段

    如何在 xaml 中引用类的静态属性 换句话说 我想做这样的事情 Class BaseThingy public static readonly Style BaseStyle
  • 在 C# 中将 ANSI (Windows 1252) 转换为 UTF8

    I ve 之前问过这个 https stackoverflow com q 4351985 398713之前在 Stack Overflow 上以一种迂回的方式 这次想把它做好 如何将 ANSI 代码页 1252 转换为 UTF 8 同时保
  • 如何在VS2017中从.net项目引用netstandard项目?

    我有一个 netstandard2 0 项目 用于与第三方 Web 服务交互 我需要在同一解决方案中引用旧的 net 4 6 2 项目中的该项目 但是当我这样做时 我会收到一堆关于需要引用我定义的类型的错误 例如 我将调用 netstand
  • 如何判断应用程序是否是Web应用程序

    在 Windows 服务和 Web 应用程序中运行的核心程序集中 我需要存储每个用户会话的信息 该服务将具有单个用户会话 并且 Web 应用程序使用 HttpContext Current 我想配置在核心程序集中使用哪种方法 约定优于配置
  • 如何证明 .NET CLR JIT 每次运行只编译每个方法一次?

    There s 一个老问题 https stackoverflow com questions 1255803 does the net clr jit compile every method every time 1255832每次询问
  • 面向对象的铸造错误[重复]

    这个问题在这里已经有答案了 将派生类强制转换为基类 我有一个通用的基本抽象类 继承自 IComparable 其定义如下 public abstract class BaseClass
  • 具有子列表属性映射问题的自动映射器

    我有以下型号 Models public class Dish Required public Int64 ID get set Required public string Name get set Required public str
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin

随机推荐

  • 如何填充页面网格并将内容宽度布置在单列中?

    我正在尝试为网络开发创建弹性框列 然而 我所能做的就是制作一列弹性盒 有哪些基本 CSS 代码可以验证 div 卡是否始终填充页面网格 并且宽度足够小 内容会布局在单列中 charset utf 8 CSS Code section dis
  • 为 matplotlib Slider 小部件设置刻度标签

    The slider https matplotlib org stable api widgets api html highlight slider matplotlib widgets Slidermatplotlib 中的行为随着最
  • ValueError:无法在空集合上计算 LDA(无术语)

    当尝试计算较小规模的语料库的 lda 时 在 python 中出现此错误 但在其他情况下工作正常 语料库的大小是 15 我尝试将主题数设置为 5 然后将其减少到 2 但它仍然给出相同的错误 ValueError 无法在空集合上计算 LDA
  • 计算流中的元素数并返回 Integer 而不是 long

    我需要计算流中的元素并将其分配给一个整数而不进行强制转换 count 确实返回很长 想到了 collect Collectors reducing 但无法弄清楚 我觉得有一些简单的事情我不明白 My Try Stream
  • bootstrap datepicker 设置日期格式 dd/mm/yyyy

    我必须以 dd mm yyyy 格式在日期选择器中设置日期 我想用 Javascript 做的是这样的 var year 2014 var month 5 var day 10 var realDate new Date year mont
  • 使用 Swift CFunctionPointer 将回调传递给 CoreMIDI API

    目前这可能实际上是不可能的 这将是不幸的 我正在尝试调用 CoreMIDI API 来设置 MIDI 输入 这就是我在 Swift 中尝试做的事情 var midiClient MIDIClientRef var inputPort MID
  • 使用 Ruby Enterprise Edition,gems 没有安装在我期望的位置

    我刚刚安装了 Ruby Enterprise Edition 并正在为其安装一些 gem 服务器上还安装了 Stock Ruby 1 8 6 我已经添加了 opt ruby enterprise 1 8 6 20090201 bin to
  • Rails 3:fields_for 在编辑视图上显示空白字段

    在我的 Rails 3 应用程序中 我在 form for 中使用 fields for 来创建和编辑问题和答案 但我在 fields for 上的编辑视图寻求答案时遇到问题 当我在数据库中为 1 个问题注册了 2 个答案时 编辑视图会显示
  • 在 NSTableCellView firstResponder() 中制作 NSTextField

    对于那些不想阅读 20 条评论来寻找答案的人 这对我有用 tableView 是基于视图 而不是基于单元格 属性检查器 tableView reloadData 不够快 使用 insertRow at 0 withAnimation lef
  • 离子标签徽章

    我正在尝试在选项卡中的图标上添加徽章 目前的结果是 http play ionic io app decfc14cb171 http play ionic io app decfc14cb171 有谁知道如何将它们放在每个图标的右上角 我尝
  • .htaccess 重写:子域作为 GET 参数,文件路径 afterdomain 完好无损

    我想使用 htaccess 将子域重写为 get 参数 但保持域后面的所有内容不变 将参数添加到末尾或 url 期望的结果 http mpmain example com gt index php http www example com
  • 在运行时创建 JMS 队列 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个应用程序 应用程序用户可以在其中创建 删除队列 此外 他还能够将消息从一个队列移动到另一个队列 删除消息 根据某些过滤器重新排列队
  • 处理 UI 上未启动的触摸

    我寻求一种方法来处理不在 Unity 引擎中的 UI 元素上启动的触摸 其目的是在 地图 上进行旋转 平移和放大 以下简称 地图 但是 如果触摸事件发生在任何 UI 元素上 则应由该 UI 元素而不是地图来处理 我认为这样的例子之一就是 G
  • ruby net-sftp 逐行读取文件

    我正在使用 ruby 2 0 0 和 Rails 4 0 0 我有类似的东西 require net sftp sftp Net SFTP start ftp app com username password gt password sf
  • 如何在 gradle 中排除传递项目依赖项

    given dependencies compile project subproject transitive false 这在 gradle 1 3 中无法正常工作 即所有依赖项都包含在子项目中 这是一个错误还是有不同的语法来排除项目
  • 带有 jQ​​uery 的 JavaScript 命名空间

    如何管理依赖于 jQuery 的自定义 JavaScript 库的命名空间 你是否创建自己的命名空间 比如说foo并在那里添加你的对象 例如foo myClass foo myFunction 或者将对象添加到 jQuery 的命名空间中
  • ngOnDestroy 和 $('#element').foundation('destroy');

    我正在尝试在我的 Angular2 应用程序中实现 Sticky Magellan 一旦我离开视图 我想删除该插件 因为否则当我重新访问视图时我会遇到问题 所以我正在使用 ngOnDestroy void element foundatio
  • XQuery 正则表达式可以匹配空字符吗?

    我想从字符串中删除所有 NULL 字符 我知道正确的正则表达式匹配应该是 x00 并且我已经尝试了以下 XQuery replace message x00 它会导致错误 exerr ERROR Conversion from XPath2
  • 从自定义文档属性中的日期获取第二天

    我有包含日期 的自定义文档属性 定义为日期 我试图从自定义文档属性 日期字段 中的日期获取第二天 DOCPROPERTY DateFieldTest 1 d MMMM YYYY toggle DOCPROPERTY Field 07 04
  • C++/CLI 委托作为函数指针 (System.AccessViolationException)

    我一直在尝试使用 C CLI 委托 因为我正在尝试创建 NET 参考库 并且遇到了以下问题 我在 C CLI 中定义一个委托 然后在 C 中创建该委托的实例 然后通过函数指针通过非托管 C 调用该委托的实例 这一切都按预期进行 说明这一点的