Strange return value

Q&A's, tips, howto's
Locked
HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Strange return value

Post by HPW »

I get a strange return value from a imported function:

Code: Select all

(get-string(hpwGetVar "[NBMode]"))
R

(string"["(get-string(hpwGetVar "[NBMode]"))"]")
[R]

(nbget "[NBMode]")
\016

(if (=(nbget "[NBMode]")"R")"Runtime""Design")
Runtime

(if (=(get-string(hpwGetVar "[NBMode]"))"R")"Runtime""Design")
Runtime

nbget
(lambda (nbvar) (get-string (hpwGetVar nbvar)))
(define (nbget nbvar) (get-string(hpwGetVar nbvar)))

I have no explanation why there is the \016-return.
But it is the direct return from the newlisp-call.
Ideas?
Hans-Peter

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

There are two possibilities:
(1) hpwGetVar is manipulating the memory around the string address passed to it from newLISP, which it should not.

but more probable:

(2) the return string, of which the address is coming back from hpwGetVar, was allocated on the stack of hpwGetVar call and disappears afterwards. The fact, that it worked in the first place is just luck. The string you are alllocating for the result gets destroyed before the newLISP (get-string ...) can copy it.

A better model for you function hpwGetVar may be to pass it a second pointer to preallocated memory in newLISP:

(set 'ptr-mem " ") ;; long enough fo result

(hpwGetVar "[NBMode]" ptr-mem)

ptr-mem => "R"

It's a bit clumsy, but this is how most Win32 DLL APIs work when strings get returned. They never return strings directly, you always have to pass a pointer and frequently a maximum size for the string to be produced too.

If you don't do it this way. You would need to allocate memory for the new string when you call hpwGetVar in the hpw.dll itself and would need some other function call to free that memory again. This is how many database APIs work, becuase they have to allocate a lot of memory for query results.

Another possibility would be to let hpw.dll have a preallocated area for hpwGetVar string results. That area would be reused everytime. But in this case you have to make sure to get the string out with (get-string ...) before you call hpwGetVar again.

Lutz

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

Thanks for the tips!

I now use:

Code: Select all

(define (allocate n)               ;from Nigel
    (pack(string "s" n)" "))

(define (nbget nbvar nbsize nbvalue)
    (setq nbvalue(allocate (+ nbsize 1)))
    (hpwGetVar nbvar nbvalue)
    (slice nbvalue 0 (find "\000" nbvalue)))
(nbget "[PubDir]" 255)

Works better.
;-)
Hans-Peter

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

For allocating space you could use the faster:

(dup " " n)
or
(dup "\000" n)

'dup' was introduced in 8.0.12 (after Nigel's example ;) )

Lutz

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

and instead of

(slice nbvalue 0 (find "\000" nbvalue))

you could do:

(string nbvalue)
or
(get-string nbvalue) ;; may be faster

The 'string' and the 'get-string' function both cut off at the \000. When a string is passed to 'get-string' is takes the address of it. In most yuu would pass an address itself to 'get-string', but you also can plug a string into it.

Lutz

Locked