Memptr to LongChar

DevTeam

Member
I have a MEMPTR which contains 40000 characters. I would like to retrieve those chars into a char variable, which is impossible with a standard CHAR var (limit : 32k). That's why I use a LONGCHAR.

The following code works, but I think there is a better way to do it.

Code:
DEF VAR ptr AS MEMPTR NO-UNDO.
DEF VAR str AS CHAR NO-UNDO.
DEF VAR str2 AS CHAR NO-UNDO.
DEF VAR strSize AS INT NO-UNDO.
DEF VAR bigStr AS LONGCHAR NO-UNDO.
DEF VAR i AS INT NO-UNDO.


/* Put 40000 chars into the MEMPTR */
DO i = 1 TO 2000 :
  str = str + "0123456789".
END.

SET-SIZE(ptr) = 0.
strSize = LENGTH(str).
SET-SIZE(ptr) = 2 * strSize + 1.
PUT-STRING(ptr,1) = str.
PUT-STRING(ptr,strSize + 1) = str.


/* Copy MEMPTR into LONGCHAR */
COPY-LOB FROM ptr STARTING AT 1 FOR (2 * strSize) TO bigStr.
DISP LENGTH(bigStr).

Any idea ?

Thanks in advance.

Julien
 

joey.jeremiah

ProgressTalk Moderator
Staff member
I have a MEMPTR which contains 40000 characters. I would like to retrieve those chars into a char variable, which is impossible with a standard CHAR var (limit : 32k). That's why I use a LONGCHAR.

The following code works, but I think there is a better way to do it.

Code:
DEF VAR ptr AS MEMPTR NO-UNDO.
DEF VAR str AS CHAR NO-UNDO.
DEF VAR str2 AS CHAR NO-UNDO.
DEF VAR strSize AS INT NO-UNDO.
DEF VAR bigStr AS LONGCHAR NO-UNDO.
DEF VAR i AS INT NO-UNDO.


/* Put 40000 chars into the MEMPTR */
DO i = 1 TO 2000 :
  str = str + "0123456789".
END.

SET-SIZE(ptr) = 0.
strSize = LENGTH(str).
SET-SIZE(ptr) = 2 * strSize + 1.
PUT-STRING(ptr,1) = str.
PUT-STRING(ptr,strSize + 1) = str.


/* Copy MEMPTR into LONGCHAR */
COPY-LOB FROM ptr STARTING AT 1 FOR (2 * strSize) TO bigStr.
DISP LENGTH(bigStr).
Any idea ?

Thanks in advance.

Julien



do what better ?

maybe theres a few minor things i would do differently but overall looks good.

i don't see any problems with using a longchar and copy-lob if you're worried about that.


don't forget to free memptrs of course, unlike chars and other scoped resources you'll need to manage these yourself even widget-pools won't do any good here.

i'd recommend also using some kind of home grown exception handling to help avoiding memory leaks.

i've got a some libraries for that, actually i'm thinking of putting them on the hive as soon as i have the time.

Code:
define var str as longchar no-undo.
define var ptr as memptr no-undo.

set-size( ptr ) = 60000.

put-string( ptr,     1, 30000 ) = fill( " ", 30000 ).
put-string( ptr, 30001, 30000 ) = fill( " ", 30000 ).



copy-lob from ptr to str.

message length( str ) view-as alert-box.

set-size( ptr ) = 0.
 

DevTeam

Member
Hi Joey,

Thanks for you quick answer.

Well, my real problem is when I use this with a DLL (which I talked about in a precedent topic). The MEMPTR returned by the external procedure points towards the physical address of the data I want to retrieve, so a GET-STRING works perfectly but the "GET-SIZE" function of this MEMPTR returns 0...

In the case of variables > 32k, I want to use a LONGCHAR / COPY-LOB but I need the GET-SIZE to return the true value of my MEMPTR otherwise the COPY-LOB crashes !!!

For the moment, I have to store this size into my DLL and call a method from my 4GL program in order to do a "SET-SIZE" before the COPY-LOB...

As I'm not sure my explanation is clear, here's the code :
Code:
RUN reception(OUTPUT ptr). /* DLL method */

[FONT=Verdana]/* Here, a GET-SIZE() would return 0 ... */[/FONT]

RUN getLastSize(OUTPUT mySize). /* DLL method */
mySize = mySize - 1.
SET-SIZE(ptr) = mySize.

DEFINE VARIABLE ret AS LONGCHAR NO-UNDO.

COPY-LOB FROM ptr STARTING AT 1 FOR mySize TO ret.

That's why I was looking for a way to use COPY-LOB without needing the size...

By the way, I would be very interested in your Exception librairies ;)
 

joey.jeremiah

ProgressTalk Moderator
Staff member
Hi Julien,

regarding get-size( ) i think thats always been the case.

for example, usually in win32 api's strings have a fixed size buffer for the maximum possible size and the returned string is null terminated that in turn also determines the string size.

that probably won't be suitable or efficient in this case if the buffer could be very, very big and the sizes could vary substantially. how about returning both the pointer-value and its size in the same function ? seems like the reasonable thing to do.

progress will let use set-size on the returned memptr for boundary checks etc. although, you have to be really careful in this case not to free the memptr twice which could lead to the session crashing.

overall memptrs management is really clunky in progress. keep in mind that in progress your first, last and every structure type are temp-tables, that's it.

about the exception handling library, i'm planning on uploading it and a bunch of other libraries to the hive as soon as i have some time. hth
 

joey.jeremiah

ProgressTalk Moderator
Staff member
funny, somebody might have over heard us :)

this just came in the progress alert and notification service -

ID: P125242
Title: "How to pass more than 32K of data from a MEMPTR to a LONGCHAR variable"
 
Top