首页 文章

在.NET平台调用中使用不安全的struct *作为opaque类型而不是IntPtr是否有效?

提问于
浏览
3

.NET Platform Invoke主张将指针类型声明为IntPtr . 例如,以下内容

[DllImport("mylib")]
static extern IntPtr get_foo();

[DllImport("mylib")]
static extern void do_something_foo(IntPtr foo);

但是,我发现当与具有许多指针类型的有趣本机接口连接时,将所有内容展平为IntPtr使得代码非常难以阅读并消除了编译器可以执行的典型类型检查 .

我一直在使用一种模式,我声明一个不安全的结构是一个不透明的指针类型 . 我可以将此指针类型存储在托管对象中,编译器可以为我进行类型检查 . 例如:

class Foo {
   unsafe struct FOO {};  // opaque type
   unsafe FOO *my_foo;

   class if {
     [DllImport("mydll")]
     extern static unsafe FOO* get_foo();

     [DllImport("mydll")]
     extern static unsafe void do_something_foo(FOO *foo);
   }

   public unsafe Foo() {
     this.my_foo = if.get_foo();     
   }
   public unsafe do_something_foo() {
     if.do_something_foo(this.my_foo);
   }

注意:我不是要编组一个结构 . DLL提供了一个我不应该触摸的不透明指针,我只需要将它提供给将来调用DLL .

我知道发布的方法是IntPtr,但我不喜欢使用无类型指针 . 当托管类型和本机代码之间存在多种指针类型时,使用IntPtrs非常危险 . 使用我的opaque结构指针类型进行类型检查是天赐之物 .

我在实践中使用这种技术没有遇到任何麻烦 . 但是,我还没有看到任何人使用这种技术的例子,我想知道为什么 . 在.NET运行时看来,上述代码是否有任何原因无效?

我的主要问题是.NET GC系统如何处理“不安全的FOO * my_foo” . 我希望因为底层类型是一个结构,并且它被声明为不安全,GC会忽略它 .

这个指针是GC系统试图追踪的东西,还是只是忽略它?使用我的技术而不是IntPtr是否安全?

2 回答

  • -1

    似乎答案是“是”......“不安全的指针被视为值类型”,这意味着使用它们来存储不透明类型是安全的 . 从某种意义上说,它们就像IntPtr一样工作,但它们带有额外的类型检查,因为不同类型的不安全指针不被认为是相同的,就像它们将它们全部设为IntPtr一样 .

    有关该主题的更详细的文章,请查看..

    http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=1210&aid=339290

  • 2

    我不会使用不安全的代码和指针 . 为什么不简单地定义结构并让CLR进行映射:

    [StructLayout(LayoutKind.Sequential)]
    public struct Foo
    {
        public int Field1;
        public long Field2;
    }
    

    然后:

    [DllImport("mylib")]
    static extern void do_something_foo(ref Foo foo);
    

相关问题