保持 PInvoked 方法存活

2024-01-09

这是我的 C 代码:

    LIBRARY_API bool __cdecl Initialize(void (*FirstScanForDevicesDoneFunc)(void));

下面是使用此 DLL 的 C# PINvoke 代码:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void FirstScanForDevicesDoneFunc();

    [DllImport("Native.dll", CallingConvention=CallingConvention.Cdecl)]
    public static extern bool Initialize(FirstScanForDevicesDoneFunc);

当我这样调用这个方法时:

    static public void Init() {
        Initialize(FirstScanForDevicesDone);
    }

    static public void FirstScanForDevicesDone() {
        //do something
    }

在......的最后Init()当回调到来时我得到空引用异常。所以我使用 Thread 来保持它并且一切正常,但我对这个解决方案不满意:

    static public bool Working = true;

    static public void Init() {
        new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;

            Initialize(FirstScanForDevicesDone);
            while (Working)
            {
                Thread.Sleep(1000);
            }
        }).Start();
    }

有没有更复杂的方法来保持这个功能?


所以我使用 Thread 来保留它,一切正常

不,该线程实际上并不能解决问题。它只是looks就像它一样,测试调试版本和使用调试器的副作用。在您将发布版本交付给客户后,它仍然会以完全相同的方式崩溃。当然是最糟糕的失败。为什么它seems就像线程解决它的解释一样这个帖子 https://stackoverflow.com/a/17131389/17034.

您需要解决真正的问题,您将委托对象传递给本机代码,但在 Init() 方法完成后,不再有对该对象的可见引用。垃圾收集器无法查看本机代码内部以查看它的使用情况。因此,当本机代码在此之后进行回调时,下一次垃圾收集将销毁该对象,kaboom。请注意,您通常会从调试器助手那里收到措辞强烈的警告,请确保您没有通过射击信使来解决问题。

正确的修复方法是:

   static FirstScanForDevicesDoneFunc callbackDelegate;

   static public void Init() {
        callbackDelegate = new FirstScanForDevicesDoneFunc(FirstScanForDeviceDone);
        Initialize(callbackDelegate);
   }

The 回调委托变量确保 GC 始终可以看到对该对象的引用。当本机代码无法再进行回调时,您可以将其设置回 null。通常不会。

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

保持 PInvoked 方法存活 的相关文章

  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 如何使用C从http下载文件?

    最近几天我试图弄清楚如何从 URL 下载文件 这是我对套接字的第一个挑战 我用它来了解协议 所以我想在没有 cURL 库的情况下只用 C 语言来完成它 我搜索了很多 现在我可以打印页面的源代码 但我认为这与文件不同 我不必只将接收到的数据从
  • 在 LINQ 查询中进行转换

    是否可以在 LINQ 查询中进行强制转换 为了编译器的缘故 下面的代码并不糟糕 但最好将其放入一个查询中 Content content dataStore RootControl as Controls Content List
  • 未找到 DEADLINE 调度策略

    我想在 C 中实现 DEADLINE 调度策略 我知道该功能已实现Linux 3 14 10我正在使用 Ubuntu 14 04Linux 3 17 0 031700 lowlatency 201410060605 SMP PREEMPT这
  • 大量互斥体对性能的影响

    假设我有一个包含 1 000 000 个元素的数组 以及多个工作线程 每个线程都操作该数组中的数据 工作线程可能会使用新数据更新已填充的元素 但每个操作仅限于单个数组元素 并且独立于任何其他元素的值 使用单个互斥锁来保护整个数组显然会导致高
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 从图像创建半透明光标

    是否可以从图像创建光标并使其半透明 我目前正在拍摄自定义图像并覆盖鼠标光标图像 如果我可以将其设为半透明 那就太好了 但不是必需的 销售人员喜欢闪亮的 目前正在做这样的事情 Image cursorImage customImage Get
  • 注入包含接口的所有已注册实现的 Enumerable

    给出以下接口 public interface IMyProcessor void Process 我希望能够注册多个实现 并让我的 DI 容器将它们的可枚举注入到这样的类中 public class MyProcessorLibrary
  • 使用任一默认捕获模式时,这是通过复制捕获还是 (*this) 通过引用捕获?是一样的吗?

    当我看到以下工作时我有点困惑 struct A void g void f g 但后来我发现this https stackoverflow com a 16323119 5825294答案非常详细地解释了它是如何工作的 本质上 它归结为t
  • C# 可以为控制台应用程序部分类“程序”类吗?

    我想知道是否可以将为任何控制台应用程序创建的默认 程序 类更改为部分类 我想这样做是因为我想要更好的组织 而不是将所有方法都放在按区域分类的 1 个文件中 对我来说 将某些方法类别放在单独的文件中会更有意义 我对分部类的理解是 它是多个文件
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • MPI - 发送和接收列

    我需要从一个进程发送矩阵列并从另一个进程接收它 我尝试运行以下程序 但得到了一个奇怪的结果 至少我这么认为 仅复制矩阵的第一个元素 某些矩阵元素会发生意外变化 include
  • 在 clang 中向量化函数

    我正在尝试根据此用 clang 对以下函数进行矢量化铿锵参考 http llvm org docs Vectorizers html 它采用字节数组向量并根据以下条件应用掩码this RFC https www rfc editor org
  • C++网络序列化[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种将 C 数据包序列化为网络流的解决方案 我在这里看到很多帖子提到人们 ACE 谷歌协议缓
  • 在一个解决方案中调用不同项目的方法

    1 个解决方案中有 3 个项目 我对第一个项目中的主文件进行的主要操作 但是我需要调用第三个项目中的方法并使用类 例如 第三个项目有 public DataClasses1DataContext base global WindowsFor
  • 在 Visual Studio 2012 Express 中设置 C++ 调试环境

    我需要调试的应用程序需要设置环境变量 这在 Visual Studio 2012 中似乎非常复杂 我想做类似的事情 set path c foo c bar c windows c program files application set
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 异步/等待 - 是*并发*吗?

    我一直在考虑 C 5 中新的异步内容 并且出现了一个特殊问题 据我了解 await关键字是一个简洁的编译器技巧 语法糖来实现连续传递 http en wikipedia org wiki Continuation passing style
  • 使用通用存储库模式和流畅的 nHibernate

    我目前正在开发一个中型应用程序 它将访问不同站点上的 2 个或更多 SQL 数据库等 我正在考虑使用类似的东西 http mikehadlow blogspot com 2008 03 using irepository pattern w

随机推荐