got this code to copy ByteArrayToMemptr, now, how to copy from memptr to Byte[]? - Forum - OpenEdge Development - Progress Community

got this code to copy ByteArrayToMemptr, now, how to copy from memptr to Byte[]?

 Forum

got this code to copy ByteArrayToMemptr, now, how to copy from memptr to Byte[]?

This question is answered

Got this from good'ol Mike:

    /**
     * Purpose: Converts a .NET Byte[] to an ABL MEMPTR
     * Notes:
     * @param poBytes The System.Byte[] to convert to a MEMPTR
     * @return The new MEMPTR with the data from the Byte[]
     */
    METHOD PUBLIC STATIC MEMPTR ByteArrayToMemptr (poBytes AS "System.Byte[]":U):
 
        DEFINE VARIABLE memptr      AS MEMPTR        NO-UNDO .
        DEFINE VARIABLE oIntPointer AS System.IntPtr NO-UNDO .
 
        SET-SIZE (memptr) = poBytes:Length . 
        oIntPointer = NEW System.IntPtr (GET-POINTER-VALUE (memptr)). 
        System.Runtime.InteropServices.Marshal:Copy (poBytes, 0, oIntPointer, poBytes:Length). 
        RETURN memptr .
 
        FINALLY:
            DELETE OBJECT oIntPointer.
        END FINALLY.
 
    END METHOD .
 

 

- See more at: https://community.progress.com/community_groups/openedge_development/f/19/t/29886#sthash.oLUHlnNx.dpuf

But now I have stored some value i got from this, but how can I use it back on ABL as a byte[]?...

Any clue will be appreciated.  Thanks,

Verified Answer
  • Here's the other direction

    METHOD PUBLIC STATIC "System.Byte[]" MemptrToByteArray( pmptr AS MEMPTR ):
        DEFINE VARIABLE nPtr   AS System.IntPtr   NO-UNDO.
        DEFINE VARIABLE vInt   AS INTEGER         NO-UNDO.
        DEFINE VARIABLE nBytes AS "System.Byte[]".
        
        vInt = GET-SIZE(pmPtr).
        nBytes = NEW "System.Byte[]"(vInt).
        nPtr = NEW System.IntPtr(GET-POINTER-VALUE(pmPtr)).
        System.Runtime.InteropServices.Marshal:Copy(nPtr, nBytes, 0, vInt).
        
        RETURN nBytes.
        FINALLY:
          nPtr = ?.
          set-size(pmPtr) = 0.
          nBytes = ?.
        END.
            
      END METHOD.
      
All Replies
  • You have a memptr now with some data. You can start to look at the GET-BYTES() and GET-STRING() functions. Also useful is the GET-SIZE() function.  There’s doc at documentation.progress.com/.../using-memptr-to-reference-external-data.html (don’t work that it’s for 11.6. The principles are the same).
     
    Be aware that *you* - yes you young man – are in charge of that memory. I would strongly recommend that in the calling block you add FINALLY:
        SET-SIZE(memptr) = 0.
    END FINALLY.
    So that you don’t end up with memory leaks.
  • Here's the other direction

    METHOD PUBLIC STATIC "System.Byte[]" MemptrToByteArray( pmptr AS MEMPTR ):
        DEFINE VARIABLE nPtr   AS System.IntPtr   NO-UNDO.
        DEFINE VARIABLE vInt   AS INTEGER         NO-UNDO.
        DEFINE VARIABLE nBytes AS "System.Byte[]".
        
        vInt = GET-SIZE(pmPtr).
        nBytes = NEW "System.Byte[]"(vInt).
        nPtr = NEW System.IntPtr(GET-POINTER-VALUE(pmPtr)).
        System.Runtime.InteropServices.Marshal:Copy(nPtr, nBytes, 0, vInt).
        
        RETURN nBytes.
        FINALLY:
          nPtr = ?.
          set-size(pmPtr) = 0.
          nBytes = ?.
        END.
            
      END METHOD.
      
  • As a matter of fact, I have the value in a BLOB on database..

    so should I..?

    DEFINE VAR mpVAR1 AS MEMPTR NO-UNDO.
    DEFINE VAR bTemplate AS "System.Byte[]"          NO-UNDO. COPY-LOB FROM table1.BlolbField TO OBJECT mpVAR1
    bTemplate = MemptrToByteArray( mpVAR1 ).

    and use the value on bTemplate as my BYTE[] array...

    (hope this works for other newbies in the future)

  • Thanks!!!!

  • This will work everywhere (ie not just Windows platforms).
  • Just a small nuance on the MemptrToByteArray method.

    With 11.7 get-pointer-value will often return a 64 bit integer (see knowledgebase.progress.com/.../Windows-API-call-fails-with-error-13712-in-11-7-64-bit). For some reason the get-pointer-value function is fooling System.IntPtr to think it is going to be 32-bit (at compile time) resulting in a too large for int32 error at run-time.

    Introducing an intermediate int64 to store the value of get-pointer-value resolves this.