.NET Platform Invoke 提倡将指针类型声明为 IntPtr。例如,以下
[DllImport(“mylib”)] 静态 extern IntPtr get_foo(); [DllImport(“mylib”)] 静态 extern void do_something_foo(IntPtr foo);
然而,我发现,当与具有许多指针类型的有趣本机接口交互时,将所有内容扁平化为 IntPtr 会使代码非常难以阅读,并消除编译器可以执行的典型类型检查。
我一直在使用一种模式,将不安全的结构声明为不透明的指针类型。我可以将此指针类型存储在托管对象中,编译器可以为我对其进行类型检查。例如:
类 Foo {
不安全的结构 FOO {};// 不透明类型
不安全的 FOO *my_foo;
类如果{
[DllImport(“mydll”)]
extern static unsafe FOO* get_foo();
[DllImport(“mydll”)]
extern static unsafe void do_something_foo(FOO *foo);
}
公共不安全 Foo() {
this.my_foo = if.get_foo();
}
公共不安全 do_something_foo() {
if.do_something_foo(this.my_foo);
}
注意:我并不是想整理一个结构。DLL 提供了一个不透明的指针,我不应该触及它,我只需要将它提供给将来对 DLL 的调用。
我知道已发布的执行此操作的方法是 IntPtr,但我不喜欢使用非类型化指针。当有多种指针类型在托管代码和本机代码之间移动时,使用 IntPtrs 是非常危险的。使用我的不透明结构指针类型进行类型检查是天赐之物。
我在实践中使用这种技术没有遇到任何问题。然而,我还没有看到任何人使用这种技术的例子,我想知道为什么。是否有任何原因导致上述代码在 .NET 运行时看来无效?
我的主要问题是.NET GC 系统如何处理“不安全的 FOO *my_foo”。我的希望是,因为底层类型是一个结构体,并且它被声明为不安全,所以 GC 会忽略它。
GC 系统是否会尝试跟踪该指针,或者只是忽略它?使用我的技术代替 IntPtr 安全吗?
看来答案是“是”......“不安全的指针被视为值类型”,这意味着使用它们来存储不透明类型是安全的。从某种意义上说,它们的工作方式与 IntPtr 类似,但它们带有额外的类型检查,因为不同类型的不安全指针不被视为相同,而如果将它们全部设为 IntPtr,则它们会被视为相同。
有关我就该主题撰写的更详细的文章,请查看..
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=1210&aid=339290
| 归档时间: |
|
| 查看次数: |
1952 次 |
| 最近记录: |