有没有一种安全的方法在.NET 4.0之前的C#中执行指针运算?

时间:2013-12-22 22:38:15

标签: c# pointers

我今天晚上发现,我写的一些帮助代码是由于将64位指针转换为32位而在64位计算机上发生相当令人讨厌的SIGSERV崩溃的罪魁祸首。

class FastPixelEditor {
    Bitmap m_bitmap;
    Rectangle m_source;
    BitmapData m_bitmapData;
    int m_nativePixelPointer;
    public FastPixelEditor(Bitmap bitmap, Rectangle source) {
        m_bitmap = bitmap;
        m_source = source;
        m_bitmapData = m_bitmap.LockBits(source, 
            ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        m_nativePixelPointer = m_bitmapData.Scan0.ToInt32();
    }
    public void SetPixel(int x, int y, Color color) {
        int idx = (y - m_source.Top) * m_source.Width + 
            (x - m_source.Left); 
        idx *= 4;
        Marshal.WriteInt32((IntPtr)(m_nativePixelPointer + idx), 
            color.ToArgb());
    }
    public Color GetPixel(int x, int y) {
        int idx = (y - m_source.Top) * m_source.Width + 
            (x - m_source.Left);
        idx *= 4;
        return Color.FromArgb(Marshal.ReadInt32((IntPtr)(
            m_nativePixelPointer + idx)));
    }
    public void Unlock() { m_bitmap.UnlockBits(m_bitmapData); }
}

崩溃发生在GetPixel函数的这一行:

Marshal.ReadInt32((IntPtr)(m_nativePixelPointer + idx))

作为帮助代码,我怀疑强迫任何使用此代码的人在他们的项目上设置/unsafe编译标志是谨慎的,但使用IntPtr.ToInt64()似乎真的是hackish(虽然它可能有效)。

IntPtr.Add似乎正是我所追求的,但此代码必须以.NET 2.0为目标,并且在.NET 4.0中添加了IntPtr.Add

我是否被迫在/unsafeIntPtr.ToInt64()之间作出决定,还是有其他选择?

2 个答案:

答案 0 :(得分:3)

注意到Marshall.ReadInt32Marshall.WriteInt32实际上有重载,允许指定偏移量:

Marshall.ReadInt32(IntPtr ptr, int ofs)

它们在.NET 2.0中可用。

答案 1 :(得分:2)

IntPtr.Add的定义如下:

return ptr + offset;

operator+的{​​{1}}重载定义如下:

IntPtr

所以..它基本上按照你的建议行事......它只是把它包装在一个更好的函数调用中。你也可以这样做。