游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3619|回复: 8

[zt] 托管代码中的指针

[复制链接]

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
发表于 2007-8-15 16:06:00 | 显示全部楼层 |阅读模式
托管代码中的指针

-------------------------------------------

interior_ptr<type>
是native pointer的超集,native pointer能做的,Interior pointer也一样能做。当垃圾回收器移动对象时,Interior pointer能随之移动,并始终指向该对象。
------《Pro Visual C++_CLI and the .NET 2.0 Platform》p815

Interior_ptr可以指向引用句柄、值类型、装箱类型句柄、托管类成员、托管数组的元素。不能指向引用类型本身。

*ip 是ip所值的类型type的值
&ip 是ip指向托管堆中的地址

-------------------------------------------

pin_ptr<type>
在外部调用托管堆中指针时,垃圾回收过程中该指针会发生改变,引起外部调用的错误。必须使用pin_ptr指针将该指针固定。

pinned pointer可以指向引用句柄、值类型、托管数组的元素。不能指向引用类型,但能指向引用类型的成员(不支持钉住由 new 表达式返回的整个对象。相反,需要钉住内部成员的地址。--MSDN)。可以完成native pointer的所有的功能,如指针比较和指针运算。

都不能由跟踪句柄直接赋值。而是必须由&操作符取地址。因为interior_ptr pin_ptr是独立的类,只能由地址赋值,而不能由托管类型赋值。

int^ m_int = gcnew int(100);
interior_ptr<int> ipint = &*m_int; //ok
interior_ptr<int> ipint = m_int;   //error
Value class Vtest{}
Ref class Rtest{}

Vtest ^vtest = gcnew Vtest;        //值类型对象

pin_ptr< Vtest > pinp;
pinp = vtest;            //error
pinp = &* vtest;        //ok
interior_ptr< Vtest > ip;
ip = &* vtest;        //ok


pin_ptr< Vtest ^> pinhundle;
pinhundle = vtest;        //error
pinhundle = & vtest;        //ok
interior_ptr< Vtest ^> iphundle;
iphundle = & vtest;        //ok


RTest ^rtest = gcnew RTest;        //引用类型对象
pin_ptr< Rtest > pinp;             //error , 不可以钉住引用类型对象
interior_ptr < Rtest > pinp;    //error , 不可以指向引用类型对象


ref class G {
public:
   void incr(int* pi) { *pi += 1; }
};
ref struct H { int j; };
void f( G^ g ) {
   H ^ph = gcnew H;
   Console::WriteLine(ph->j);
   pin_ptr<int> pj = &ph->j;    //ok,可以钉住引用类型对象的成员
   g->incr(  pj );
   Console::WriteLine(ph->j);
}

   
---------------------------------------------


Pin_ptr指针使用例子
value class Test
{
public:
    int i;
};

#pragma unmanaged
void incr (int *i)
{
    (*i) += 10;
}

#pragma managed
void main ()
{
    Test ^test = gcnew Test();
    interior_ptr<int> ip = &test->i;
    (*ip) = 5;
//  incr( ip );            // invalid
    pin_ptr<int> i = ip;   // i is a pinned int pointer
    incr( i );             // pinned pointer to interior pointer passed to a
                           // native function call expecting a native pointer
    Console::WriteLine ( test->i );
}


非托管代码中的函数void incr(int *i)需要int指针,不能将interior_ptr<int>的ip传递给该函数。因为内部指针会随着垃圾回收改变地址,而将其转换为pin_ptr<int>,就是将地址固定,以供外部函数incr(int* i)调用该指针。

-----------------------------------------------

和*指针的转换
正因为pin_ptr<>所指向的地址是固定的,因此才能和*指针转换。而interior_ptr<>无此性质。
    pin_ptr<ClassValue> pValue = &value;;
    ClassValue* p = pValue;            //ok


interior_ptr就不可以和*指针转换。    interior_ptr<ClassValue> pValue = &value;;
    ClassValue* p = pValue;            //error


-----------------------------------------------
  

值类型的指针
在新语法中,值类型指针分为两种类型:V*(限于非 CLR 堆位置)和内部指针 interior_ptr<V>(允许但不要求托管堆内的地址)。
// may not address within managed heap
V *pv = 0;

// may or may not address within managed heap
interior_ptr<V> pvgc = nullptr;
托管扩展中的下列声明全部映射到新语法中的内部指针。(它们是 System命名空间内的值类型。)
Int32 *pi;   // => interior_ptr<Int32> pi;
Boolean *pb; // => interior_ptr<Boolean> pb;
E *pe;       // => interior_ptr<E> pe; // Enumeration
内置类型不被认为是托管类型,尽管它们确实在System命名空间内作为类型的别名。

26

主题

537

帖子

537

积分

高级会员

Rank: 4

积分
537
发表于 2007-8-15 16:34:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

既然已经托管了,VB.Net使用指针自然还是Marshal来的方便,如果不是Windows程序开发史的后遗症,后来的VB程序员又何必哭着喊着要用到指针?

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
 楼主| 发表于 2007-8-15 16:57:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

Marshal是类库,怎么可能会比语言直接支持的方便

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
 楼主| 发表于 2007-8-15 17:06:00 | 显示全部楼层

Re: [zt] 托管代码中的指针

在VB.net中完成interior_ptr或pin_ptr的功能的话,就要用到类库中的GCHandle,无论效率还是方便上看都不如在C++/CLI

而且VB.net用GCHandle也只能得到一个广义上的地址IntPtr,无法做到类型安全

26

主题

537

帖子

537

积分

高级会员

Rank: 4

积分
537
发表于 2007-8-16 09:10:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

托管指针的效率还不如原型数组,如果会VC++的话,在指针方面使用托管就实在有点莫名其妙了,Marshal正因为是类库所以对VB.Net来说才用得方便,当然前提是只会VB不懂C++

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
 楼主| 发表于 2007-8-16 16:17:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

不明白你说的托管指针是什么,这里的interior_ptr和pin_ptr或是类库里GCHandle得到的指针都是非托管指针

26

主题

537

帖子

537

积分

高级会员

Rank: 4

积分
537
发表于 2007-8-17 11:13:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

我的意思说白了就是:
1、VB.Net想使用指针就得将非托管代码托管起来
2、这样的指针效率不高,不到必要时不用为好
3、到了不得不用时,对于只会VB不懂C++的人,作为类库内容的Marshal和GCHandle更容易掌握

29

主题

475

帖子

483

积分

中级会员

Rank: 3Rank: 3

积分
483
发表于 2007-8-17 12:40:00 | 显示全部楼层

Re:[zt] 托管代码中的指针

看C++就像看鸟文一样 看不懂

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
 楼主| 发表于 2007-8-17 17:57:00 | 显示全部楼层

Re: Re:[zt] 托管代码中的指针

系统崩溃: Re:[zt] 托管代码中的指针

1、VB.Net想使用指针就得将非托管代码托管起来
2、这样的指针效率不高,不到必要时不用为好
3、到了不得不用时,对于只会VB不懂C++的人,作为类库内容的Marshal和GCHandle更容易掌握


1 不是要在VB.net中使用指针,而是把托管的数据交给非托管代码处理
2 这样的指针效率已经是最高的了……
3 确实是个问题,不过这里的C++/CLI仅是用于沟通托管与非托管代码,还是比较简单的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 10:33

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表