.NET平台调用主张将指针类型声明为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是否安全?
答案 0 :(得分:2)
似乎答案是“是”......“不安全的指针被视为值类型”,这意味着使用它们存储不透明类型是安全的。从某种意义上说,它们就像IntPtr一样工作,但它们带有额外的类型检查,因为不同类型的不安全指针不被认为是相同的,就像它们将它们全部设置为IntPtr一样。
有关该主题的更详细的文章,请查看..
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=1210&aid=339290
答案 1 :(得分:-1)
我不会使用不安全的代码和指针。为什么不简单地定义结构并让CLR进行映射:
[StructLayout(LayoutKind.Sequential)]
public struct Foo
{
public int Field1;
public long Field2;
}
然后:
[DllImport("mylib")]
static extern void do_something_foo(ref Foo foo);