Strange return value

Started by HPW, December 07, 2004, 04:14:47 AM

Previous topic - Next topic

HPW

I get a strange return value from a imported function:



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

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

(nbget "[NBMode]")
16

(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 16-return.

But it is the direct return from the newlisp-call.

Ideas?
Hans-Peter

Lutz

#1
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

#2
Thanks for the tips!



I now use:

(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 "00" nbvalue)))


(nbget "[PubDir]" 255)



Works better.

;-)
Hans-Peter

Lutz

#3
For allocating space you could use the faster:



(dup " " n)

or

(dup "00" n)



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



Lutz

Lutz

#4
and instead of



(slice nbvalue 0 (find "00" 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 00. 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