一个难倒无数高手(发在微软新闻组上到现在还没好的解决方案)的问题,有关数据转换

weijl 2003-07-29 03:52:57
分别有三个结构体,如下:
[ StructLayout( LayoutKind.Sequential )]
public struct ONL_POINT //点
{
public int x, y;
}

[ StructLayout( LayoutKind.Sequential )] //线
public struct ONL_STROKE
{
public IntPtr pPoint;
public int pointNum;
}

[ StructLayout( LayoutKind.Sequential )] //字
public struct ONL_STROKES
{
public IntPtr pStroke;
public int strokeNum;
}


ONL_POINT[] points1 = new ONL_POINT[2];
points1[0].x = 1;
points1[0].y = 1;
points1[1].x = 99;
points1[1].y = 99;

ONL_POINT[] points2 = new ONL_POINT[2];
points2[0].x = 99;
points2[0].y = 1;
points2[1].x = 1;
points2[1].y = 99;

ONL_STROKE[] strokes = new ONL_STROKE[2];
int size = Marshal.SizeOf( typeof(ONL_POINT) );
IntPtr buffer1 = Marshal.AllocHGlobal(size*points1.Length );
for (int i = 0; i < points1.Length; i++)
{
IntPtr temp;
temp = new IntPtr( buffer1.ToInt32() + i * size );
Marshal.StructureToPtr( points1[i], temp, false );
}
strokes[0].pPoint = buffer1;
strokes[0].pointNum = points1.Length;

IntPtr buffer2 = Marshal.AllocHGlobal( size * points2.Length );
for (int i = 0; i < points2.Length; i++)
{
IntPtr temp;
temp = new IntPtr( buffer2.ToInt32() + i * size );
Marshal.StructureToPtr( points2[i], temp, false );
}
strokes[1].pPoint = buffer2;
strokes[1].pointNum = points2.Length;


ONL_STROKES stroke_data;
size = Marshal.SizeOf( typeof(ONL_STROKE) );
IntPtr buffer3 = Marshal.AllocHGlobal( size * strokes.Length );
int[] buffer4 = new int[strokes.Length];
for (int i = 0; i < strokes.Length; i++)
{
IntPtr temp;
temp = new IntPtr( buffer3.ToInt32() + i * size );
Marshal.StructureToPtr( strokes[i], temp, false );
buffer4[i] = temp.ToInt32();
}
IntPtr buffer5 = Marshal.AllocHGlobal( IntPtr.Size * strokes.Length );
Marshal.Copy(buffer4, 0, buffer5, strokes.Length);
stroke_data.pStroke = buffer5;
stroke_data.strokeNum = strokes.Length;
以上是将代表二条线的四点转换为ONL_STROKES,因为要调用dll,dll接口为ONL_STROKES,所以要如此复杂的转换,这个转换肯定对。问题是反过来,将ONL_STROKES型转换为ONL_POINT型中的x,y就有问题了。我的写法如下
假设ONL_STROKES strokes已有值

ONL_STROKE[] stroke = new ONL_STROKE[strokes.strokeNum];
int size = Marshal.SizeOf( typeof(ONL_STROKE) );


for(int i = 0; i < strokes.strokeNum;i++ )
{
IntPtr temp;
temp = new IntPtr( strokes.pStroke.ToInt32() + i*size );
stroke[i] = (ONL_STROKE)Marshal.PtrToStructure(temp,typeof(ONL_STROKE));
}

ONL_POINT[][] point = new ONL_POINT[strokes.strokeNum][];
size = Marshal.SizeOf( typeof(ONL_POINT) );

for(int j = 0; j < strokes.strokeNum;j++ )
{
point[j] = new ONL_POINT[stroke[j].pointNum];
for(int k = 0; k <stroke[j].pointNum; k++ )
{
IntPtr temp;
temp = new IntPtr( stroke[j].pPoint.ToInt32() + k * size );
point[j][k] = (ONL_POINT)Marshal.PtrToStructure(temp, typeof(ONL_POINT));
}

}

for(int j = 0; j < strokes.strokeNum;j++ )
{

for(int k = 0; k <stroke[j].pointNum; k++ )
{
int a = point[j][k].x;
a = point[j][k].y;
}

}
但是一运行数据都不对,请问各位高手如何解决?
...全文
20 7 打赏 收藏 举报
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
Gao2003 2003-07-30
  • 打赏
  • 举报
回复
你的代码比较多,这样吧,我把我的声明及调用贴出来,你可参考一下。

声明如下:
[StructLayout(LayoutKind.Sequential)]
public class stru1
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class stru2
{
public int num;
public IntPtr dd; //Point to stru1
}

[DllImport(@"D:\MyTestProgram\TestHelp\Release\TestHelp.dll")]
public static extern int SetStruct( [MarshalAs(UnmanagedType.LPStruct)] stru2 dd);

调用函数如下:
private stru1[] TestAPI(stru1[] str)
{
stru2 k=new stru2();
int strbytes=Marshal.SizeOf(typeof(stru1));
k.num=str.Length;
k.dd=Marshal.AllocCoTaskMem(strbytes*k.num);
for(int i=0;i<k.num;i++)
{
Marshal.StructureToPtr(str[i],(IntPtr)((int)(k.dd)+strbytes*i),true);
}
int rint=UsbApi.SetStruct(k);
stru1[] stru1s=new stru1[k.num];
for(int i=0;i<k.num;i++)
{
stru1 strtemp=(stru1)Marshal.PtrToStructure((IntPtr)((int)(k.dd)+strbytes*i),typeof(stru1));
stru1s[i]=strtemp;
}
Marshal.FreeCoTaskMem(k.dd);
return stru1s;
}

调用如下:
stru1 s1=new stru1();
s1.x=1;
s1.y=1;
stru1 s2=new stru1();
s2.x=2;
s2.y=2;
stru1 s3=new stru1();
s3.x=9;
s3.y=10;
stru1 s4=new stru1();
s4.x=12;
s4.y=12;
stru1[] strs=new stru1[]{s1,s2,s3,s4};
strs=TestAPI(strs);

说明:
1.在VC结构声明中,最好显示声明x,y为4Byte,如
struct stru1
{
LONG x;//最好不要用int
LONG y;
}
因为你在C#中声明为int(是4Byte)
2.在C#中最好不要用struct来声明结构。而用类来声明,我试了用结构来声明,根本不能调用。所以我声明为
[StructLayout(LayoutKind.Sequential)]
public class stru1
{
public int x;
public int y;
}
把结构声明为类,不知道你们怎么能调用。学习学习。
3.Marshal.StructureToPtr函数的第三个参数到底是true还是false。我看了帮助也不知道用那个,我用true试了可以调用,所以用true.这样用可以防止内存泄漏。关于此用法不知对否,还请高手指点。
4.我只是用了两种结构,还用一种("字"结构)没用到,应该差不多。以上如有错误还望各位指正。
weijl 2003-07-30
  • 打赏
  • 举报
回复
我自己解决啦,谢谢大家,解决方案如下:
ONL_STROKE[] stroke = new ONL_STROKE[strokes.strokeNum];
int size = Marshal.SizeOf(typeof(ONL_STROKE));
int [] buffer = new int [strokes.strokeNum];
Marshal.Copy(strokes.pStroke,buffer,0,strokes.strokeNum);


for(int i = 0; i < strokes.strokeNum;i++ )
{
IntPtr temp;
temp = (IntPtr)buffer[i];
stroke[i] = (ONL_STROKE)Marshal.PtrToStructure(temp,typeof(ONL_STROKE));
}

ONL_POINT[][] point = new ONL_POINT[strokes.strokeNum][];
size = Marshal.SizeOf( typeof(ONL_POINT) );

for(int j = 0; j < strokes.strokeNum;j++ )
{
point[j] = new ONL_POINT[stroke[j].pointNum];
for(int k = 0; k <stroke[j].pointNum; k++ )
{
IntPtr temp;
temp = new IntPtr( stroke[j].pPoint.ToInt32() + k * size );
point[j][k] = (ONL_POINT)Marshal.PtrToStructure(temp, typeof(ONL_POINT));
}

}
这其中的难点是非托管内存指针向托管内存指针之间的转换
panyee 2003-07-29
  • 打赏
  • 举报
回复
ConsoleApplication1:DebugOutput
handle:0
strk:ONL_STROKES
.pStroke:1412640
.pStroke[0]:
->pPoint:1343456
->pPoint[0]:
.x:1
.y:1
->pPoint[1]:
.x:99
.y:99
->pointNum:2
->rect:ONL_RECT
.orgx:0
.orgy:0
.xsize:100
.ysize:100
.pStroke[1]:
->pPoint:1412688
->pPoint[0]:
.x:99
.y:1
->pPoint[1]:
.x:1
.y:99
->pointNum:2
->rect:ONL_RECT
.orgx:0
.orgy:0
.xsize:100
.ysize:100
.strokeNum:2
.rect:ONL_RECT
.orgx:0
.orgy:0
.xsize:100
.ysize:100
uid:0



我的运行结果是这个, 但不知你正确的要是什么?
lovered 2003-07-29
  • 打赏
  • 举报
回复
[v]
panyee 2003-07-29
  • 打赏
  • 举报
回复
把整个项目发来吧, 这样看起来太费劲

panyee@263.net
panyee 2003-07-29
  • 打赏
  • 举报
回复
这么多代码....
好运 2003-07-29
  • 打赏
  • 举报
回复
看看
相关推荐
发帖
C#

10.8w+

社区成员

.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
帖子事件
创建了帖子
2003-07-29 03:52
社区公告

让您成为最强悍的C#开发者