本文介绍了从COM服务器将C#中的复杂结构编组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我在弄清楚如何从COM服务器对象将嵌套结构传递到C#时遇到了概念上的问题.
说我具有以下结构MY_PLACEMENT:

typedef struct
{
短整数x;
短整数y;
} MY_POINT; /* size = 4 */

typedef struct {
double dScale;
long lNumPoints;
MY_POINT points [4];
} MY_CENTROID; /* size = 12 + 16 = 38 */

typedef结构体
{
短整数x;
短整数y;
长xRaw;
yRaw long;
short int ID;
short int iSeenNear;
MY_CENTROID重心[4];
} MY_PLACEMENT; /* size = 20 + 152 = 172 */

在C ++中,我可以使用SAFEARRAY(byte)提取一个MY_PLACEMENTs数组,我知道从safeArray的大小来看MY_PLACEMENT的数量( 172 = 1,344 = 2,依此类推),因此在接收端,我只使用CopyMemory.例如,如果safeArray的大小为344,则为(i = 0; i< 2; i ++)
CopyMemory(& myArray [i])定义MY_PLACEMENT myArrray [2]和

safeArray-> pData +(i * sizeof(MY_PLACEMENT),sizeof(MY_PLACEMENT));

我完成了.

在.NET中,我可以找回一个托管对象.字节数组,可以说在这种情况下我有344个是两个MY_PLACEMENT,但是由于无法在C#中定义具有固定数组大小的结构,因此没有简单的块复制内存的方法.看来我必须使用嵌套函数来解析字节数组,但是即使这样,在这种情况下,我仍然看不到没有BytePtr数据类型的情况.即使MY_PLACEMENT结构是DWORD对齐的,我想我也可以使用IntPtr:

ParseTouchPoint(ref Placement mp,IntPtr pBytes)
{
//假设我通过将MY_PLACEMENT结构对齐为四个字节来固定
mp.x =(short int)pBytes;
pBytes ++;
mp.y =(short int)pBytes;
pBytes ++;
mp.xRaw = pBytes;
pBytes + = 4;
........我< mp.iNumCentroids; = ++){
ParseCentroid(ref mp.centroids [i],pBytes;
)pBytes + = 13;/* IntPtr一次增加4个字节*/
} >}

ParseCentroid(ref Centroid cent,IntePtr pBytes)
{
cent.dScale =(ref double)pBytes;//为此,我需要一个DoublePtr
pBytes + = 2;
cent.lNumpoints =(IntPtr)pBytes;
pBytes ++;
//再次更改MY_POINT以使用long而不是short int进行DWORD对齐
/>(int i = 0; i< cent.lNumPoints; i ++){
tp.points [i] .x = pBytes; .y = pBytes;
pBytes ++;
}
非托管内存然后被搞砸了,我看不到Marshal.ReadDouble()(我可以将ReadInt16()
和ReadInt32()用于其他所有功能....

彼得

I am having conceptual problems figuring out how to pass nested structures to C# from a COM server object.
Say I have the following struct MY_PLACEMENT :

typedef struct
{
    short int x;
    short int y;
} MY_POINT ; /* size = 4 */

typedef struct   {
    double  dScale;
    long    lNumPoints;
    MY_POINT  points[4];
} MY_CENTROID; /* size = 12 + 16 = 38 */

typedef struct 
{
    short int x;
    short int y;
    long xRaw;
    long yRaw;
    short int ID;
    short int iSeenNear;
    MY_CENTROID centroids[4];
} MY_PLACEMENT;  /* size = 20 + 152 = 172 */

In C++ I can just use a SAFEARRAY(byte) to abstract an array of MY_PLACEMENTs, I know the number of MY_PLACEMENTs in the safeArray from its size (172 = one, 344 = two, etc), so on the receiving end I just use CopyMemory.  For instance if the safeArray size is 344 I define MY_PLACEMENT myArrray[2]  and

for (i = 0; i < 2; i++)
    CopyMemory(&myArray[i], safeArray->pData + (i * sizeof(MY_PLACEMENT), sizeof(MY_PLACEMENT));

and I am done. 

In .NET I can get back a managed array of bytes, lets say I got 344 in this case is two MY_PLACEMENTs, but there is no easy way of block copying the memory since I can’t define a struct with a fixed array size in C#.  It looks like I have to use nested functions to parse the byte array, but even then I don't see how I can get the pieces out without a BytePtr data type in this case.  However even if the MY_PLACEMENT structure is DWORD aligned I suppose I could use an IntPtr:

ParseTouchPoint(ref Placement mp, IntPtr pBytes)
{
// lets assume I fixed the MY_PLACEMENT struct to by aligned on four bytes
         mp.x = (short int) pBytes;
         pBytes++;
         mp.y = (short int) pBytes;
         pBytes++;
         mp.xRaw = pBytes;
         pBytes +=4;
       …..
         For (int I = 0; I < mp.iNumCentroids; =++) {
              ParseCentroid(ref mp.centroids[i], pBytes;
              pBytes += 13;  /* an IntPtr increments 4 bytes at a time */
         }
}

ParseCentroid (ref Centroid cent, IntePtr pBytes)
{
         cent.dScale = (ref double) pBytes;  // I need a DoublePtr for this
         pBytes += 2;
         cent.lNumpoints = (IntPtr)pBytes;
         pBytes ++;
// again I change the MY_POINT to use long instead of short int to be DWORD aligned
         for (int i = 0; i < cent.lNumPoints; i++) {
              tp.points[i].x = pBytes;
              pBytes++;
              tp.points[i].y = pBytes;
              pBytes++;
         }
}


So with the exception of the double everything might work, if the SafeArray was actually considered
unmanaged memory then I'm screwed b/c I don't see how Marshal.ReadDouble() (I can use ReadInt16()
and ReadInt32() for everything else....

Peter

推荐答案


这篇关于从COM服务器将C#中的复杂结构编组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 23:10