【问题标题】:Sharing memory between managed and unmanaged code with P/Invoke使用 P/Invoke 在托管代码和非托管代码之间共享内存
【发布时间】:2014-11-03 06:34:44
【问题描述】:

我为 C++ 库创建了一个 C 包装器,并从我的 C# 托管代码中调用此 C 包装器。我面临的问题是这个库涉及数千次迭代和长运行时间。显然,我需要一种与 C# 程序通信并更新 C/C++ 库正在进行的处理状态的方法。

直截了当的方法是在固定数量的迭代后返回,更新状态并再次调用 C/C++ 包装器。但处理依赖于一些基于 C++ STL 的数据结构,这些数据结构在每次迭代后都会更新。我的托管代码不需要这些数据结构,但显然它们必须保存在内存中以进行所有迭代。

所以在处理完成之前我不能从 C/C++ 包装器返回,否则 C++ 结构将被释放...

我认为最好的方法是在托管代码和非托管代码之间共享一些变量,并每 N 次迭代读取一次处理状态。但这又引出了另一个问题:如何同步访问这块内存?

【问题讨论】:

  • 为什么当包装器返回时数据结构会被释放?
  • 因为它们是由被调用函数分配的。使用全局变量或未释放的动态内存似乎是一种肮脏且不稳定的解决方案。我可以确定在调用包装器后不会清除此动态内存或全局变量吗?如果 DLL 被卸载了怎么办?

标签: c# .net pinvoke


【解决方案1】:

您可以在 C++ 代码中将 C# 委托注册为回调。这样,您不必从包装器返回,但您的包装器可以通过回调调用 C# 委托,然后可以继续处理。您的委托还可以包含一些参数,您可以使用这些参数在 C# 和 C++ 层之间交换数据。

查看更完整的描述here

这里的主要技巧是使用方法GetFunctionPointerForDelegate,它允许您从 C# 委托创建 C++ 函数指针,以便您可以从 C++ 层调用您的 C# 代码。

【讨论】:

  • 这不需要技巧,pinvoke marshaller 已经使用 GFPFD 来编组代表。
  • 谢谢。因为我是 P/Invoke 的初学者,所以我不知道这个功能。这似乎是实现状态更新的最佳方法。
  • @Hans Passant。谢谢,很高兴知道,上次我只在 C++/CLI 包装器中使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 2011-01-29
相关资源
最近更新 更多