从非托管 C 库访问 C# 方法是不是安全? [关闭]

Posted

技术标签:

【中文标题】从非托管 C 库访问 C# 方法是不是安全? [关闭]【英文标题】:Is it safe to access a method of C# from an unmanaged C library? [closed]从非托管 C 库访问 C# 方法是否安全? [关闭] 【发布时间】:2015-10-02 03:34:45 【问题描述】:

我现在正在从 C 访问 C# 的方法。下面是 C# 中的一些 sn-p 代码。

IntPtr pFunc = Marshal.GetFunctionPointerForDelegate (
    new DelegateForMyMethodInCsharp (
        MyMethodInCsharp
    )
);

setFuncPtr(pFunc);

setFuncPtr() 是一个 C 库的函数,用于设置 C# 方法的指针。在这段代码之后,我可以随时调用 C 库中的 C# 方法而不会出现任何问题,但我不确定这是否可以。

在 C# 中对存储在堆中的变量使用指针时,由于 GC,必须使用关键字 'fixed'。因为内存的堆栈部分包含方法,所以像上面那样编写代码对我来说是有意义的。但是因为我还没有看到有人这样写,所以我希望听到你的意见。

这是一个非常简单的问题,但对我来说是一个非常重要的问题。 我不想写不安全的代码。

【问题讨论】:

它是否“安全”在很大程度上取决于实际的方法。我们看不到它,只有当你真正尝试和测试它时,你才会感觉更好。你弄错了这个 sn-p,但你会得到一个很好的调试器警告。当你真正尝试和测试它时。 感谢您的建议 :) 【参考方案1】:

您需要确保委托实例没有被垃圾回收。

为此,您可以简单地将其存储在一个字段中,并确保只要非托管代码挂在指针上,该字段就已植根。

这是必要的,因为委托不仅存储指向 .Net 方法的指针,还存储状态(第一个参数;通常为 this)。要为此创建一个函数指针,运行时必须创建一个引用此对象的 thunk,以便非托管代码可以从函数指针中获取。这受委托实例的生命周期的限制。

有关委托和函数指针之间区别的更多信息,请参阅my blog。

【讨论】:

感谢您直言不讳!我很傻,根本没有考虑委托的实例!我只是以为我写的代码会直接将内存地址传递给C,就像不安全块中的变量一样。再次感谢! 顺便说一句,你说“要做到这一点,你可以简单地将它存储在一个字段中,并确保只要非托管代码挂在指针上,该字段就被植根。”,你确定这样做会解决问题吗?我不认为这会有所帮助,因为我们在不安全块中使用关键字“fixed”的原因是为了防止变量不仅被删除,而且被 GC“移动”。如果我无法固定委托,即使委托实例仍然存在,我也无法从 C 访问。 附言。看了你的文章,很喜欢! @Jenix:别担心;运行时将为您处理。

以上是关于从非托管 C 库访问 C# 方法是不是安全? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何从非托管 C++ 代码获取结构化列表值到 C#?

使用 COM 互操作从非托管 C++ 访问 c# 属性

从非托管 c++ 调用 C# 函数(通过托管包装器)

从非托管 C++ mfc active x dll 启动 C# 对话框

将数组从非托管 C++ 传递到 C#

从 c# 访问 C++ .lib 库