.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 回答
似乎答案是“是”......“不安全的指针被视为值类型”,这意味着使用它们来存储不透明类型是安全的 . 从某种意义上说,它们就像IntPtr一样工作,但它们带有额外的类型检查,因为不同类型的不安全指针不被认为是相同的,就像它们将它们全部设为IntPtr一样 .
有关该主题的更详细的文章,请查看..
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=1210&aid=339290
我不会使用不安全的代码和指针 . 为什么不简单地定义结构并让CLR进行映射:
然后: