www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there any convenient CopyMemory function in Phobos?

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Apparently in the Windows API there's a whole lot of byte-copying going around.

Here's an example:

int CALLBACK EnhMetaFileProc (HDC hdc, HANDLETABLE * pHandleTable,
                              CONST ENHMETARECORD * pEmfRecord,
                              int iHandles, LPARAM pData)
{
     ENHMETARECORD * pEmfr ;

     pEmfr = (ENHMETARECORD *) malloc (pEmfRecord->nSize) ;

     CopyMemory (pEmfr, pEmfRecord, pEmfRecord->nSize) ;

     if (pEmfr->iType == EMR_RECTANGLE)
          pEmfr->iType = EMR_ELLIPSE ;

     PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfr, iHandles) ;

     free (pEmfr) ;

     return TRUE ;
}

The nSize field specifies the byte size of the structure pointed to by
pEmfRecord. The reason copying is required is because of this code:
     if (pEmfr->iType == EMR_RECTANGLE)
          pEmfr->iType = EMR_ELLIPSE ;

pEmfRecord itself is const, so new memory has to be allocated first
and then the memory from pEmfRecord is copied there, and then the
iType field is changed. A simple pointer dereference won't copy all
the bytes, since this is one of those variable-length structure types
you often see in C code.

In D I've used the slice trick to assign a byte range of data from one
memory location to another:
extern (Windows)
int EnhMetaFileProc(HDC hdc, HANDLETABLE* pHandleTable,
                    const ENHMETARECORD* pEmfRecord,
                    int iHandles, LPARAM pData)
{
    ENHMETARECORD* pEmfr;
    immutable newlength = pEmfRecord.nSize;

    pEmfr = cast(ENHMETARECORD*)GC.malloc(newlength);

    (cast(ubyte*)pEmfr)[0..newlength] = (cast(ubyte*)pEmfRecord)[0..newlength];

    if (pEmfr.iType == EMR_RECTANGLE)
        pEmfr.iType = EMR_ELLIPSE;

    PlayEnhMetaFileRecord(hdc, pHandleTable, pEmfr, iHandles);

    GC.free(pEmfr);
    return TRUE;
}

That's quite ugly.. Is there a Phobos/Druntime and maybe
platform-independent function that can do byte-memory copies in a
simple way? Something like this is what I need:
CopyBytes(dest, src, bytecount);

Btw, CopyMemory is a WinAPI specific function, but I can't even link
to it (it's actually an alias to RtlCopyMemory, but it's not in
kernel32.lib for some reason even though MSDN says it is).
Jun 13 2011
parent "annonimous" <digitalmars.D.learn puremagic.com> writes:
See you need copy only if     if (pEmfRecord->iType ==
EMR_RECTANGLE).
You can cast it and check it, else you perform with old
parameters.

Something like this

        if (pEmfRecord->iType == EMR_RECTANGLE)
        {
           pEmfr->iType = EMR_ELLIPSE ;

           PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfr,
iHandles) ;

           free (pEmfr) ;
       }
       else
            PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfRecord,
iHandles) ;

On Monday, 13 June 2011 at 23:31:56 UTC, Andrej Mitrovic wrote:
 Apparently in the Windows API there's a whole lot of 
 byte-copying going around.

 Here's an example:

 int CALLBACK EnhMetaFileProc (HDC hdc, HANDLETABLE * 
 pHandleTable,
                               CONST ENHMETARECORD * pEmfRecord,
                               int iHandles, LPARAM pData)
 {
      ENHMETARECORD * pEmfr ;

      pEmfr = (ENHMETARECORD *) malloc (pEmfRecord->nSize) ;

      CopyMemory (pEmfr, pEmfRecord, pEmfRecord->nSize) ;

      if (pEmfr->iType == EMR_RECTANGLE)
           pEmfr->iType = EMR_ELLIPSE ;

      PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfr, iHandles) 
 ;

      free (pEmfr) ;

      return TRUE ;
 }

 The nSize field specifies the byte size of the structure 
 pointed to by
 pEmfRecord. The reason copying is required is because of this 
 code:
      if (pEmfr->iType == EMR_RECTANGLE)
           pEmfr->iType = EMR_ELLIPSE ;

 pEmfRecord itself is const, so new memory has to be allocated 
 first
 and then the memory from pEmfRecord is copied there, and then 
 the
 iType field is changed. A simple pointer dereference won't copy 
 all
 the bytes, since this is one of those variable-length structure 
 types
 you often see in C code.

 In D I've used the slice trick to assign a byte range of data 
 from one
 memory location to another:
 extern (Windows)
 int EnhMetaFileProc(HDC hdc, HANDLETABLE* pHandleTable,
                     const ENHMETARECORD* pEmfRecord,
                     int iHandles, LPARAM pData)
 {
     ENHMETARECORD* pEmfr;
     immutable newlength = pEmfRecord.nSize;

     pEmfr = cast(ENHMETARECORD*)GC.malloc(newlength);

     (cast(ubyte*)pEmfr)[0..newlength] = 
 (cast(ubyte*)pEmfRecord)[0..newlength];

     if (pEmfr.iType == EMR_RECTANGLE)
         pEmfr.iType = EMR_ELLIPSE;

     PlayEnhMetaFileRecord(hdc, pHandleTable, pEmfr, iHandles);

     GC.free(pEmfr);
     return TRUE;
 }

 That's quite ugly.. Is there a Phobos/Druntime and maybe
 platform-independent function that can do byte-memory copies in 
 a
 simple way? Something like this is what I need:
 CopyBytes(dest, src, bytecount);

 Btw, CopyMemory is a WinAPI specific function, but I can't even 
 link
 to it (it's actually an alias to RtlCopyMemory, but it's not in
 kernel32.lib for some reason even though MSDN says it is).
Jul 05 2013