大家知道,VB.NET/C#在指针的使用上是受到很多限制的。虽然C#提供了unsafe代码的指针访问,但还是有不少限制。.NET Framework的类库提供了GCHandle类库和Marshal命名空间内存访问方法,但一来速度比较慢,二来访问时(譬如基于数组和结构的数据转化)需要重新创建对象。
因此,我用C++/CLI写了个内存指针访问类库,解决了VB.NET内存指针访问的难题。
下面是一个字符串拷贝示例:
Console.WriteLine("拷贝字符串示例")
Using ptr As Pointer = Pointer.Lock(txtsrc.Text)
'方法1,直接进行字符串复制
txtdst.Text = ptr.CopyToString(txtsrc.TextLength)
Console.WriteLine("Pointer.CopyToString:{0}", txtdst.Text)
'方法2,通过CopyToObject的泛型方法复制字符串
Dim strdst As String = New String(" "c, txtsrc.TextLength)
txtdst.Text = ptr.CopyToObject(Of String)(strdst)
Console.WriteLine("Pointer.CopyToObject:{0}", txtdst.Text)
End Using '解锁对象,相当于ptr.UnLock()
'方法3,用 Shared 的 Copy 方法进行字符串复制。
Dim strdsts As String = New String(" "c, txtsrc.TextLength)
Pointer.Copy(strdsts, txtsrc.Text, 0, 0, txtsrc.TextLength * 2) ' 1 Char = 2 Bytes
txtdst.Text = strdsts
ConsoleWriteLine("Pointer.Copy:{0}", txtdst.Text)
数据类型的转换:
'测试字符串到整数
Console.WriteLine()
Console.WriteLine("读取整数:")
Using ptr As Pointer = Pointer.Lock(txtsrc.Text)
Dim lll As Integer = txtsrc.TextLength << 1 '获取字节长度
ConsoleWrite("按照字节读取数据(Bytes), Pointer.Item : ")
For i As Integer = 0 To lll - 1
Console.Write("{0:X2} ", ptr(i))
Next
Console.WriteLine()
ConsoleWrite("按照字读取数据 (Char), Pointer.Int16Item: ")
For i As Integer = 0 To (lll >> 1) - 1
Console.Write("{0} ", ptr.CharItem(i))
Next
Console.WriteLine()
ConsoleWrite("按照字读取数据 (Short), Pointer.Int16Item: ")
For i As Integer = 0 To (lll >> 1) - 1
ConsoleWrite("{0:X4} ", ptr.Int16Item(i))
Next
ConsoleWriteLine()
Console.Write("按照双字读取数据(Int ), Pointer.Int32Item: ")
For i As Integer = 0 To (lll >> 2) - 1
Console.Write("{0:X8} ", ptr.Int32Item(i))
Next
Console.WriteLine()
Console.Write("按照四字读取数据(Long ), Pointer.Int64Item: ")
For i As Integer = 0 To (lll >> 3) - 1
Console.Write("{0:X16} ", ptr.Int64Item(i))
Next
Console.WriteLine()
Console.WriteLine()
ConsoleWriteLine("拷贝到数组:")
ConsoleWrite("Bytes :")
Dim bytes As Byte() = New Byte(lll - 1) {}
ptr.CopyToArray(bytes, 0, lll)
'Pointer.Copy(bytes, ptr, 0, 0, l) '这样也可以
Console.WriteLine(BitConverter.ToString(bytes))
Console.Write("Short :")
Dim shorts As Short() = New Short((lll >> 1) - 1) {}
Pointer.Copy(shorts, ptr, 0, 0, lll) '这样也可以
For i As Integer = 0 To shorts.Length - 1
Console.Write("{0:X4} ", shorts(i))
Next
Console.WriteLine()
Console.Write("Integer:")
Dim ints As Integer() = New Integer((lll >> 2) - 1) {}
Pointer.Copy(ints, ptr, 0, 0, lll) '这样也可以
For i As Integer = 0 To ints.Length - 1
Console.Write("{0:X8} ", ints(i))
Next
Console.WriteLine()
Console.Write("Long :")
Dim longs As Long() = New Long((lll >> 3) - 1) {}
Pointer.Copy(longs, ptr, 0, 0, lll) '这样也可以
For i As Integer = 0 To longs.Length - 1
Console.Write("{0:X16} ", longs(i))
Next
Console.WriteLine()
Console.WriteLine("数据回写:")
Dim sl As Short() = New Short() {&H31, &H32, &H33, &H2020, &H3031}
Pointer.Copy(ptr, sl, 0, 0, sl.Length << 2)
ptr.CopyToArray(bytes, 0, lll)
'Pointer.Copy(bytes, ptr, 0, 0, l) '这样也可以
Console.WriteLine("写入值(Short):0x31, 0x32, 0x33, 0x2020, 0x3031")
Console.WriteLine("目标值(Byte ):{0}", BitConverter.ToString(bytes))
End Using
Console.WriteLine("对象类型转换:")
Dim pt As Point = New Point(12345, 67890)
Console.WriteLine("源对象类型:Point,{0}", pt.ToString())
Using ptr = Pointer.Lock(pt)
Console.WriteLine("转换为Pointf:{0}", ptr.CopyToObject(Of PointF)().ToString())
Console.WriteLine("转换为PointTest:{0}", ptr.CopyToObject(Of PointTest)().ToString())
End Using
其中,上面的PointTest类结构如下,与Point结构的不同是PointTest为类,Point为结构(值类型):
<StructLayout(LayoutKind.Sequential)> _
Private Class PointTest
Public x As Integer
Public y As Integer
Public Overrides Function ToString() As String
Return String.Format("x={0},y={1}", x, y)
End Function
End Class
与Marshal.Copy的速度比较。
由于用了内嵌汇编,所以拷贝速度还是比较可观的,起码比Marshal.Copy快上一点。
Pointer.Copy 循环1000000次,耗时: 2028003 Ticks
Marshal.Copy 循环1000000次,耗时: 2340004 Ticks
而且支持数组到数组、数组到指针、数组到对象、指针到指针、指针到数组、指针到对象、对象到数组、对象到指针、对象到对象等拷贝方式。
下面是比较代码:
Console.WriteLine()
Console.WriteLine("与Marshal.Copy比较拷贝速度:")
Dim buff1 As Integer() = New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Dim buff2 As Byte() = New Byte(buff1.Length << 2) {}
Dim ds As Long
Dim cnt As Integer = 1000000 '循环次数
Dim l As Integer = buff2.Length
Using ptr = Pointer.Lock(Of Integer())(buff1)
Console.Write("Pointer.Copy 循环{0}次,", cnt)
ds = Now.Ticks
Using dtr = Pointer.Lock(Of Byte())(buff2)
For i As Integer = 1 To cnt
Pointer.Copy(dtr, ptr, 0, 0, l)
Next
End Using
Console.WriteLine("耗时:{0} Ticks", (Now.Ticks - ds).ToString().PadLeft(10, " "c))
Console.Write("Marshal.Copy 循环{0}次,", cnt)
ds = Now.Ticks
For i As Integer = 1 To cnt
Marshal.Copy(ptr.Address, buff2, 0, l)
Next
Console.WriteLine("耗时:{0} Ticks", (Now.Ticks - ds).ToString().PadLeft(10, " "c))
End Using
C++/CLI源代码:
主类(CWOOD.Pointer.h):
// CWOOD.Pointer.h
#include "MemoryCopy.h"
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;
namespace CWOOD
{
#pragma region Pointer
public ref class Pointer
{
private:
int locptr,farptr;
GCHandle^ SafeHandle;
Byte* BytePtr;
Char* CharPtr;
short* Int16Ptr;
int* Int32Ptr;
Int64* Int64Ptr;
unsigned short* UInt16Ptr;
unsigned int* UInt32Ptr;
UInt64* UInt64Ptr;
float* FloatPtr;
double* DoublePtr;
int sz;
public:
#pragma region 构造函数
//用预分配内存的方式定义一个新的指针对象
Pointer(int BytesSize)
{
locptr = (int)Marshal::AllocHGlobal(BytesSize);
farptr = locptr;
BytePtr = (Byte*)farptr;
CharPtr = (Char*)farptr;
Int16Ptr = (short*)farptr;
Int32Ptr = (int*)farptr;
Int64Ptr = (Int64*)farptr;
UInt16Ptr = (unsigned short*)farptr;
UInt32Ptr = (unsigned int*)farptr;
UInt64Ptr = (UInt64*)farptr;
FloatPtr = (float*)farptr;
DoublePtr = (double*)farptr;
}
//用已有指针创建一个指针对象
Pointer(IntPtr AddressPtr)
{
locptr = 0;
farptr = (int)AddressPtr;
BytePtr = (Byte*)farptr;
CharPtr = (Char*)farptr;
Int16Ptr = (short*)farptr;
Int32Ptr = (int*)farptr;
Int64Ptr = (Int64*)farptr;
UInt16Ptr = (unsigned short*)farptr;
UInt32Ptr = (unsigned int*)farptr;
UInt64Ptr = (UInt64*)farptr;
FloatPtr = (float*)farptr;
DoublePtr = (double*)farptr;
}
Pointer(String^ value)
{
locptr = -1;
SafeHandle = GCHandle::Alloc(value,GCHandleType::Pinned);
farptr = (int)SafeHandle->AddrOfPinnedObject();
BytePtr = (Byte*)farptr;
CharPtr = (Char*)farptr;
Int16Ptr = (short*)farptr;
Int32Ptr = (int*)farptr;
Int64Ptr = (Int64*)farptr;
UInt16Ptr = (unsigned short*)farptr;
UInt32Ptr = (unsigned int*)farptr;
UInt64Ptr = (UInt64*)farptr;
FloatPtr = (float*)farptr;
DoublePtr = (double*)farptr;
}
#pragma endregion
#pragma region 析构函数
~Pointer()
{
if(locptr == farptr)
{
Marshal::FreeHGlobal((IntPtr)locptr);
}
else if(locptr == -1)
{
if(SafeHandle != nullptr)SafeHandle->Free();
}
locptr = 0;
farptr = 0;
}
#pragma endregion
#pragma region 属性
property IntPtr Address
{
IntPtr get()
{
return (IntPtr)farptr;
}
}
property Byte default[int]
{
Byte get(int offset)
{
return BytePtr[offset];
}
void set(int offset, Byte value)
{
BytePtr[offset] = value;
}
}
property Char CharItem[int]
{
Char get(int offset)
{
return CharPtr[offset];
}
void set(int offset, Char value)
{
CharPtr[offset] = value;
}
}
property short Int16Item[int]
{
short get(int offset)
{
return Int16Ptr[offset];
}
void set(int offset, short value)
{
Int16Ptr[offset] = value;
}
}
property int Int32Item[int]
{
int get(int offset)
{
return Int32Ptr[offset];
}
void set(int offset, int value)
{
Int32Ptr[offset] = value;
}
}
property Int64 Int64Item[int]
{
Int64 get(int offset)
{
return Int64Ptr[offset];
}
void set(int offset, Int64 value)
{
Int64Ptr[offset] = value;
}
}
property unsigned short UInt16Item[int]
{
unsigned short get(int offset)
{
return Int16Ptr[offset];
}
void set(int offset, unsigned short value)
{
Int16Ptr[offset] = value;
}
}
property unsigned int UInt32Item[int]
{
unsigned int get(int offset)
{
return Int32Ptr[offset];
}
void set(int offset, unsigned int value)
{
Int32Ptr[offset] = value;
}
}
property UInt64 UInt64Item[int]
{
UInt64 get(int offset)
{
return Int64Ptr[offset];
}
void set(int offset, UInt64 value)
{
Int64Ptr[offset] = value;
}
}
property ValueType^ ValueTypeItem[int]
{
ValueType^ get(int offset)
{
return BytePtr[offset<<sizeof(ValueType^)];
}
/*void set(int offset, ValueType^ value)
{
sz = sizeof(int);
BytePtr[offset<<sz] = value;
}*/
}
#pragma endregion
#pragma region 公共方法
void UnLock()
{
this->~Pointer();
}
static void UnLock(Pointer^ point)
{
point->~Pointer();
}
/**<summary>用指定数据长度创建一个 Pointer 对象</summary>
///<remarks></remarks>
///<param name="size">申请内存的长度</param>
///<returns></returns>
static Pointer^ FromSize(int size)
{
return gcnew Pointer(size);
}
/**<summary> 由指定内存地址创建一个可操作的 Pointer 对象</summary>
///<remarks></remarks>
///<param name="Address">内存地址</param>
///<returns></returns>
static Pointer^ FromAddress(IntPtr Address)
{
return gcnew Pointer(Address);
}
/**<summary>锁定一个值类型数组,以便进行内存操作</summary>
///<remarks>一个值类型数据</remarks>
///<param name="value">待锁定的数组</param>
///<returns>返回锁定该数组的 Pointer 对象</returns>
generic<class T>
static Pointer^ Lock(array<T>^ value)
{
if(IsValueType(value))
{
pin_ptr<array<T>^> ptr = &value;
Pointer^ t = gcnew Pointer((IntPtr)ptr);
return t;
}
else
{
GCHandle hnd = GCHandle::Alloc(value,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
Pointer^ t = gcnew Pointer(ptr);
t->locptr = -1;
t->SafeHandle = hnd;
return t;
}
}
/**<summary>锁定字符串,以便进行内存操作</summary>
///<remarks></remarks>
///<param name="value">待锁定的数组</param>
///<returns>返回锁定该数组的 Pointer 对象</returns>
static Pointer^ Lock(String^ value )
{
return gcnew Pointer(value);
}
/**<summary>锁定无符号长整数数组,以便进行内存操作</summary>
///<remarks>一个无符号长整数型数字,8字节大小</remarks>
///<param name="value">待锁定的数组</param>
///<returns>返回锁定该数组的 Pointer 对象</returns>
generic<class T>
static Pointer^ Lock(T% value )
{
if(IsValueType(value))
{
pin_ptr<T> ptr = &value;
Pointer^ t = gcnew Pointer((IntPtr)ptr);
return t;
}
else
{
GCHandle hnd = GCHandle::Alloc(value,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
Pointer^ t = gcnew Pointer(ptr);
t->locptr = -1;
t->SafeHandle = hnd;
return t;
}
}
/**<summary>将数据复制到目标对象</summary>
///<remarks>不支持字符串、数组等</remarks>
///<return>数据复制后的对象</return>
generic<class T>
T CopyToObject()
{
int size;
if((T::typeid)->IsValueType)
{
T obj;
size = sizeof(obj);
pin_ptr<T> dest = &obj;
Byte* destptr = (Byte*)dest;
MemoryCopy::CopySD(destptr,BytePtr,size);
return obj;
}
else
{
if((T::typeid) == (String::typeid))
{
return (T)String::Empty;//不支持字符串、数组等
}
else
{
T obj = Activator::CreateInstance<T>();
size = Marshal::SizeOf(obj);
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD((Byte*)(int)ptr,BytePtr,size);
hnd.Free();
return obj;
}
}
}
/**<summary>将数据复制到目标对象</summary>
///<remarks></remarks>
///<param name="obj">目标对象</param>
///<return>数据复制后的对象</return>
generic<class T>
T CopyToObject(T% obj)
{
int size;
if(IsValueType(obj))
{
size = sizeof(obj);
pin_ptr<T> dest = &obj;
Byte* destptr = (Byte*)dest;
MemoryCopy::CopySD(destptr,BytePtr,size);
return obj;
}
else
{
if(isinst<String^,Object^>((Object^)obj))//如果是字符串,要特殊处理
{
size = ((String^)obj)->Length<<2;
}
else
{
size = Marshal::SizeOf(obj);
}
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD((Byte*)(int)ptr,BytePtr,size);
hnd.Free();
return obj;
}
}
/**<summary>将数据复制到目标数组</summary>
///<remarks></remarks>
///<param name="obj">目标数组</param>
///<return>数据复制后的数组</return>
generic<class T>
array<T>^ CopyToObject(array<T>^ obj)
{
int size;
if (obj == nullptr || obj->Length==0) return obj;
size = obj->Length * SizeOf(obj[0]);
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD((Byte*)(int)ptr,BytePtr,size);
hnd.Free();
return obj;
}
/**<summary>将数据复制到目标数组</summary>
///<remarks></remarks>
///<param name="obj">目标数组</param>
///<param name="offset">偏移量,以数组单位长度为度量值</param>
///<param name="length">复制长度,以数组单位长度为度量值</param>
///<return>数据复制后的数组</return>
generic<class T>
array<T>^ CopyToArray(array<T>^ obj, int offset, int length)
{
int size;
if (obj == nullptr || obj->Length==0 || offset > obj->Length || length <= 0) return obj;
if(length + offset > obj->Length)length = obj->Length - offset;
size = length * SizeOf(obj[0]);
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD((Byte*)(int)ptr,BytePtr,size);
hnd.Free();
return obj;
}
/**<summary>将数据复制到目标对象</summary>
///<remarks></remarks>
///<param name="l">字符串长度</param>
///<return>数据复制后的对象</return>
String^ CopyToString(int l)
{
String^ d = gcnew String(0x0,l);
GCHandle hnd = GCHandle::Alloc(d,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD((unsigned char*)(int)ptr,BytePtr,l<<1);
hnd.Free();
return d;
}
/**<summary>从对象拷贝数据</summary>
///<remarks></remarks>
///<param name="obj">待拷贝对象</param>
generic<class T>
void CopyFromObject(T% obj)
{
int size;
if(IsValueType(obj))
{
pin_ptr<T> src = &obj;
Byte* srcptr = (Byte*)src;
int size = sizeof(obj);
MemoryCopy::CopySD(BytePtr,srcptr,size);
}
else
{
size = Marshal::SizeOf(obj);
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD(BytePtr,(Byte*)(int)ptr,size);
hnd.Free();
}
}
/**<summary>从数组拷贝数据</summary>
///<remarks></remarks>
///<param name="obj">待拷贝数组</param>
generic<class T>
void CopyFromObject(array<T>^ obj)
{
int size = obj->Length * SizeOf(obj[0]);
GCHandle hnd = GCHandle::Alloc(obj,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
MemoryCopy::CopySD(BytePtr,(Byte*)(int)ptr,size);
hnd.Free();
}
/**<summary>从字符串拷贝数据</summary>
///<remarks></remarks>
///<param name="value">待拷贝字符串</param>
void CopyFromString(String^ value)
{
GCHandle hnd = GCHandle::Alloc(value,GCHandleType::Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
Byte* srcptr = (Byte*)(int)ptr;
/*pin_ptr<String^> src = &value;
Byte* srcptr = (Byte*)src;*/
int size = (value->Length)<<1;
MemoryCopy::CopySD(BytePtr,srcptr,size);
hnd.Free();
}
/**<summary>将数据从一对象复制到另一对象</summary>
///<remarks></remarks>
///<param name="Dest">目标对象</param>
///<param name="Src">原始对象</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T1, class T2>
static void Copy(T1% Dest, T2% Src, int BytesLength)
{
Pointer^ src = Pointer::Lock(Src);
Pointer^ dst = Pointer::Lock(Dest);
MemoryCopy::CopySD(dst->BytePtr, src->BytePtr, BytesLength);
delete src;
delete dst;
}
/**<summary>将数据从一对象复制到另一对象</summary>
///<remarks></remarks>
///<param name="Dest">目标对象</param>
///<param name="Src">原始对象</param>
///<param name="DestBytesOffset">目标对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T1, class T2>
static void Copy(T1% Dest, T2% Src, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
Pointer^ src = Pointer::Lock(Src);
Pointer^ dst = Pointer::Lock(Dest);
MemoryCopy::CopySD(dst->BytePtr + DestBytesOffset, src->BytePtr + SrcBytesOffset, BytesLength);
delete src;
delete dst;
}
/**<summary>将数据从 Pointer 对象复制到指定对象</summary>
///<remarks></remarks>
///<param name="Dest">指定目标对象</param>
///<param name="Src">原始 Pointer 对象</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T>
static void Copy(T% Dest, Pointer^ Src, int BytesLength)
{
Pointer^ dst = Pointer::Lock(Dest);
MemoryCopy::CopySD(dst->BytePtr, Src->BytePtr, BytesLength);
delete dst;
}
/**<summary>将数据从 Pointer 对象复制到指定对象</summary>
///<remarks></remarks>
///<param name="Dest">指定目标对象</param>
///<param name="Src">原始 Pointer 对象</param>
///<param name="DestBytesOffset">目标对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始 Pointer 对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T>
static void Copy(T% Dest, Pointer^ Src, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
Pointer^ dst = Pointer::Lock(Dest);
MemoryCopy::CopySD(dst->BytePtr + DestBytesOffset, (Src->BytePtr)+SrcBytesOffset, BytesLength);
delete dst;
}
/**<summary>将数据从指定对象复制到目标 Pointer 对象</summary>
///<remarks></remarks>
///<param name="Dest">目标 Pointer 对象</param>
///<param name="Src">原始对象</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T>
static void Copy(Pointer^ Dest, T% Src, int BytesLength)
{
Pointer^ src = Pointer::Lock(Src);
MemoryCopy::CopySD(Dest->BytePtr, src->BytePtr, BytesLength);
delete src;
}
/**<summary>将数据从指定对象复制到目标 Pointer 对象</summary>
///<remarks></remarks>
///<param name="Dest">目标 Pointer 对象</param>
///<param name="Src">原始对象</param>
///<param name="DestBytesOffset">目标 Pointer 对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
generic<class T>
static void Copy(Pointer^ Dest, T% Src, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
Pointer^ src = Pointer::Lock(Src);
MemoryCopy::CopySD(Dest->BytePtr + DestBytesOffset, src->BytePtr + SrcBytesOffset, BytesLength);
delete src;
}
/**<summary>将数据从原始 Pointer 对象复制到目标 Pointer 对象</summary>
///<remarks></remarks>
///<param name="Dest">目标 Pointer 对象</param>
///<param name="Src">原始 Pointer 对象</param>
///<param name="DestBytesOffset">目标 Pointer 对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始 Pointer 对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
static void Copy(Pointer^ Dest, Pointer^ Src, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
MemoryCopy::CopySD(Dest->BytePtr + DestBytesOffset, Src->BytePtr + SrcBytesOffset, BytesLength);
}
/**<summary>内存数据复制</summary>
///<remarks></remarks>
///<param name="DestPtr">目标内存地址</param>
///<param name="SrcPtr">原始内存地址</param>
///<param name="BytesLength">待复制数据的字节数</param>
static void Copy(IntPtr DestPtr, IntPtr SrcPtr, int BytesLength)
{
MemoryCopy::CopySD((unsigned char*)(int)DestPtr, (unsigned char*)(int)SrcPtr, BytesLength);
}
/**<summary>将数据从一内存地址复制到另一内存地址</summary>
///<remarks></remarks>
///<param name="DestPtr">目标内存地址</param>
///<param name="SrcPtr">原始内存地址</param>
///<param name="DestBytesOffset">目标 Pointer 对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始 Pointer 对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
static void Copy(IntPtr DestPtr, IntPtr SrcPtr, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
MemoryCopy::CopySD((unsigned char*)(int)DestPtr + DestBytesOffset, (unsigned char*)(int)SrcPtr + SrcBytesOffset, BytesLength);
}
/**<summary>将数据从一内存地址复制到另一内存地址</summary>
///<remarks>托管模式,运行速度比较慢</remarks>
///<param name="d">目标内存地址</param>
///<param name="s">原始内存地址</param>
///<param name="l">待复制数据的字节数</param>
static void SafeCopy(IntPtr d, IntPtr s, int l)
{
int *pd = (int *)(int)d;
int *ps = (int *)(int)s;
int i = 0;
for (i = 0; i < l / 4; i++)
*pd++ = *ps++;
for (i = 0; i < l % 4; i++)
*(char *)pd++ = *(char *)ps++;
}
/**<summary>将数据从一 Pointer 对象复制到另一Pointer 对象</summary>
///<remarks>托管模式,运行速度比较慢</remarks>
///<param name="Dest">目标 Pointer 对象</param>
///<param name="Src">原始 Pointer 对象</param>
///<param name="DestBytesOffset">目标 Pointer 对象的目标内存地址偏移(单位:字节数)</param>
///<param name="SrcBytesOffset">原始 Pointer 对象待复制数据的内存地址偏移(单位:字节数)</param>
///<param name="BytesLength">待复制数据的字节数</param>
static void SafeCopy(Pointer^ Dest, Pointer^ Src, int DestBytesOffset, int SrcBytesOffset, int BytesLength)
{
int *pd = Dest->Int32Ptr;
int *ps = Src->Int32Ptr;
int i = 0;
for (i = 0; i < BytesLength / 4; i++)
pd[i] = ps[i];
//*pd++ = *ps++;
for (i = 0; i < BytesLength % 4; i++)
((char *)pd)[i] = ((char *)ps)[i];
//*(char *)pd++ = *(char *)ps++;
}
#pragma endregion
/**<summary>检查对象是否为值类型对象</summary>
///<remarks></remarks>
///<param name="value">待检查对象</param>
///<return>True = ValueType, False = Not ValueType.</return>
generic<class T>
static bool IsValueType(T% value)
{
return isinst<ValueType^,Object^>((Object^)value);
}
/**<summary>检查类型是否为值类型对象</summary>
///<remarks></remarks>
///<return>True = ValueType, False = Not ValueType.</return>
generic<class T>
static bool IsValueType()
{
return (T::typeid)->IsValueType;
}
/**<summary>查看对象占用内存大小</summary>
///<remarks></remarks>
///<param name="obj">待分析对象</param>
///<return>对象占用内存大小</return>
generic<class T>
static int SizeOf(T% obj)
{
if(IsValueType(obj))
{
return sizeof(obj);
}
else
{
return Marshal::SizeOf(obj);
}
}
/**<summary>查看值类型占用内存大小</summary>
///<remarks></remarks>
///<return>占用内存大小</return>
generic<class T>
where T:System::ValueType
static int SizeOf()
{
return sizeof(T);
}
private:
template < class T, class U >
static bool isinst(U u) {
return dynamic_cast< T >(u) != nullptr;
//return safe_cast< T >(u) != nullptr;
}
};
#pragma endregion
}
内存复制类(MemoryCopy.h):
#pragma once
#pragma unmanaged
private class MemoryCopy
{
public:
MemoryCopy(void)
{
}
~MemoryCopy(void)
{
}
static void CopyInt(unsigned char *d, unsigned char *s, int l)//4字节复制,适用于32位操作系统
{
int *pd = (int *)d;
int *ps = (int *)s;
int i = 0;
for (i = 0; i < l / 4; i++)
*pd++ = *ps++;
for (i = 0; i < l % 4; i++)
*(char *)pd++ = *(char *)ps++;
}
static void CopySD(unsigned char *d, unsigned char *s, int l)//用movesd拷贝
{
_asm {
mov esi, s;
mov edi, d;
mov edx, l;
mov ecx, edx;
shr ecx, 2;
rep movsd;
mov ecx, edx;
and ecx,3;
rep movsb;
}
}
static void CopyD(unsigned char *d, unsigned char *s, int l)//用movd复制
{
_asm{
mov eax,s;
mov edx,d;
mov ecx,l;
shr ecx,5;
jz done;
ll: movd mm0, qword ptr [eax];
movd mm1, qword ptr [eax+8];
movd mm2, qword ptr [eax+16];
movd mm3, qword ptr [eax+24];
movd qword ptr [edx],mm0;
movd qword ptr [edx+8], mm1;
movd qword ptr [edx+16], mm2;
movd qword ptr [edx+24], mm3;
add eax,32;
add edx,32;
dec ecx;
jnz ll;
done:
};
}
static void CopyDQU(unsigned char *d, unsigned char *s, int l)//用movdqu复制
{
_asm{
mov eax,s;
mov edx,d;
mov ecx,l;
shr ecx,7;
jz done;
ll:
movdqu xmm0, [eax];
movdqu xmm1, [eax+16];
movdqu xmm2, [eax+32];
movdqu xmm3, [eax+48];
movdqu [edx],xmm0;
movdqu [edx+16],xmm1;
movdqu [edx+32],xmm2;
movdqu [edx+48],xmm3;
add eax,64;
add edx,64
dec ecx;
jnz ll;
done:
};
}
static void CopyNTDQ(unsigned char *d, unsigned char *s, int l)//用movntdq复制
{
_asm{
mov esi,s;
mov edi,d;
mov ecx,l;
shr ecx,6;
jz done;
ll:
prefetchnta [esi];
movdqa xmm0, [esi];
movdqa xmm1, [esi+16];
movdqa xmm2, [esi+32];
movdqa xmm3, [esi+48];
movntdq [edi],xmm0;
movntdq [edi+16],xmm1;
movntdq [edi+32],xmm2;
movntdq [edi+48],xmm3;
add esi,64;
add edi,64
dec ecx;
jnz ll;
done:
};
}
};
#pragma managed