Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

External library interface

 [1/18] from: lmecir:mbox:vol:cz at: 2-Jul-2003 15:12


Hi all, I tried to help Cyphre with a specific problem (OpenGL 3D). I found a following problem in the interface between Rebol strings and external strings. First I try to make a C string usable for an external function: rebol_string: "12^(0)4" c_string: third make struct! [s [string!]] reduce [rebol_string] So far so good, I created a binary! data (in fact a pointer), that can be passed to a library function as a C string. Now let's suppose, that a library function returns a C string. How can this be done? One possibility is to store such a pointer into a Rebol integer. Not having Rebol/Command, I cannot call a library function now, but I can "simulate" this situation using the C string I prepared above. To do it, I just convert the above C string to a Rebol integer. integer_struct: make struct! [i [integer!]] none change third integer_struct c_string rebol_integer: integer_struct/i Now I obtained the C string as an integer and I can pretend, that it is a result of an external library function. What to do with it to obtain a Rebol string? Let's try to use a similar "trick" as above: result_integer_struct: make struct! [i [integer!]] reduce [rebol_integer] result_string_struct: make struct! [s [string!]] none change third result_string_struct third result_integer_struct result_string: result_string_struct/s ; == "12" Now the problem: as we have seen, the RESULT_STRING_STRUCT doesn't know the length of the string (as usual for C strings) and therefore it assumes, that the string is a null-terminated string as usual in C, so it "leaves off" a part of the string. While this is reasonable for strings, I doubt, it is reasonable for binary data, like images. Do you have any idea how to handle binary data or strings containing null characters? -L

 [2/18] from: ptretter:charter at: 2-Jul-2003 13:54


Not sure exactly what you going about doing but I use /Pro and do library calls to winapi alot. I usually define a string I want to pass to the library as: mystring: "test^@" Now if I receive a string from a library function to a pointer - in this case we will call the pointer 'outstring so what I would do on 'outstring is the following: trim/with outstring "@" Not sure if I helped you or not. Paul ----- Original Message ----- From: "Ladislav Mecir" <[lmecir--mbox--vol--cz]> To: <[rebol-list--rebol--com]> Sent: Wednesday, July 02, 2003 8:12 AM Subject: [REBOL] External library interface Hi all, I tried to help Cyphre with a specific problem (OpenGL 3D). I found a following problem in the interface between Rebol strings and external strings. First I try to make a C string usable for an external function: rebol_string: "12^(0)4" c_string: third make struct! [s [string!]] reduce [rebol_string] So far so good, I created a binary! data (in fact a pointer), that can be passed to a library function as a C string. Now let's suppose, that a library function returns a C string. How can this be done? One possibility is to store such a pointer into a Rebol integer. Not having Rebol/Command, I cannot call a library function now, but I can simulate this situation using the C string I prepared above. To do it, I just convert the above C string to a Rebol integer. integer_struct: make struct! [i [integer!]] none change third integer_struct c_string rebol_integer: integer_struct/i Now I obtained the C string as an integer and I can pretend, that it is a result of an external library function. What to do with it to obtain a Rebol string? Let's try to use a similar "trick" as above: result_integer_struct: make struct! [i [integer!]] reduce [rebol_integer] result_string_struct: make struct! [s [string!]] none change third result_string_struct third result_integer_struct result_string: result_string_struct/s ; == "12" Now the problem: as we have seen, the RESULT_STRING_STRUCT doesn't know the length of the string (as usual for C strings) and therefore it assumes, that the string is a null-terminated string as usual in C, so it "leaves off" a part of the string. While this is reasonable for strings, I doubt, it is reasonable for binary data, like images. Do you have any idea how to handle binary data or strings containing null characters? -L

 [3/18] from: nitsch-lists:netcologne at: 2-Jul-2003 22:11


Am Mittwoch, 2. Juli 2003 15:12 schrieb Ladislav Mecir:
> Hi all, > I tried to help Cyphre with a specific problem (OpenGL 3D). I found a
<<quoted lines omitted: 27>>
> Do you have any idea how to handle binary data or strings containing null > characters?
Write a wrapper-function in c. call the wrapper-function with a buffer. copy the result in the buffer.
> -L
-V

 [4/18] from: lmecir:mbox:vol:cz at: 2-Jul-2003 22:58


Hi Paul,
> Not sure exactly what you going about doing but I use /Pro and do library > calls to winapi alot.
<<quoted lines omitted: 4>>
> so what I would do on 'outstring is the following: > trim/with outstring "@"
I don't understand, how do you use it to be able to access the memory you need to.
> Not sure if I helped you or not. > > Paul
-L

 [5/18] from: lmecir:mbox:vol:cz at: 2-Jul-2003 22:49


Hi Volker, you wrote: Write a wrapper-function in c. call the wrapper-function with a buffer. copy the result in the buffer.
> -L
-V that looks reasonable, but it isn't acceptable in this case, because the memory part returned by the API function should be read and modified by Rebol. My question was, how to do it, if it contains null characters. I hope, that some work-around can be found :-o, because it is important in this case (OpenGL 3D graphics!).

 [6/18] from: Cal:prolific at: 2-Jul-2003 14:58


I think you would have to treat it as a rebol struct! type to get past the nulls. If you could tell us what function and data structure you're trying to use, maybe I can find something else that would work. I've had some success in working with OpenGL from rebol before..

 [7/18] from: ptretter:charter at: 2-Jul-2003 19:20


Well for example here is the GetWindowText function from Microsoft WINAPI as I have used it (commented): getwindowtext: make routine! [ {The GetWindowText function copies the text of the specified window's title bar (if it has one) into a buffer.} hWnd [integer!] "[in] Handle to the window or control containing the text." lpString [string!] "[out] Pointer to the buffer that will receive the text." nMaxCount [integer!] "[in] Specifies the maximum number of characters to copy to the buffer, including the NULL character." return: [integer!] {If the function succeeds, the return value is the length, in characters, of the copied string, not including the terminating NULL character.} ] winlib "GetWindowTextA" str: make string! "" ; needed to hold windows title and passed to the getwindowtext routine. loop 200 [append str "^@"] getwindowtext-ret: handle-to-a-window getwindow-next-ret str 200

 [8/18] from: rotenca:telvia:it at: 3-Jul-2003 2:46


Ciao Ladislav,
>string (as usual for C strings) and therefore it assumes, > that the string is a null-terminated string as >usual in C, so it "leaves off" a part of the string. While this > is reasonable for strings, I doubt, it is >reasonable for binary data, like images.
1) I don't have Pro or command. 2) I do not know how much is safe (look at the GC section of command doc) 3) Hope it helps :-) First we create a 36 byte data block: x: [] loop 10 [insert tail x [. [long]]] data: make struct! x none data is an area of 9 long (36 bytes)
>> third data
== #{ 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 } Now we create a struct which contains a pointer to a 36 bytes area: z: make struct! compose/deep [data [struct! [(x)]]] none
>> third z
== #{6863E500} Now, to emulate the return value of a routine, we create a second struct which contains a pointer to a different 36 byte area: res: make struct! compose/deep [data [struct! [(x)]]] none
>> third res
== #{E864E500} Now we change the first long of res for test purpose: res/data/.: 1; == 1 Now we make z to point to res 36 byte data area: change third z third res;== #{} Check the result:
>> z/data/.
== 1 In a real program, the routine should return a long (res). It must be converted to binary and poked to the third of our struct (z). To end make it an image!: img: make image! reduce [3x3 third z/data] check it:
>>img
make image! [3x3 #{ 010000000000000000000000000 000000000000000000000000000}] ------ The program --------- x: [] loop 10 [insert tail x [. [long]]] data: make struct! x none z: make struct! compose/deep [data [struct! [(x)]]] none res: make struct! compose/deep [data [struct! [(x)]]] none res/data/.: 1; == 1 change third z third res img: make image! reduce [3x3 third z/data] --- Ciao Romano

 [9/18] from: lmecir:mbox:vol:cz at: 3-Jul-2003 9:08


Hi Romano,
> 1) I don't have Pro or command.
neither do I,...
> 2) I do not know how much is safe (look at the GC section of command doc)
Garbage Collection is not a problem for the application I mentioned.
> 3) Hope it helps :-)
Yes, it works!
> First we create a 36 byte data block: > > x: [] loop 10 [insert tail x [. [long]]]
Actually, it looks like 40 bytes? Another approach using chars: x: head insert/dup [] [. [char!]] 40
> data: make struct! x none
this (together with the trick below), is a nice way, how to obtain a specific length binary! What surprises me is, that we don't need distinct names for the structure elements :-o.
> Now we create a struct which contains a pointer to a 36 bytes area: > > z: make struct! compose/deep [data [struct! [(x)]]] none > > >> third z > == #{6863E500}
Perfect!

 [10/18] from: lmecir:mbox:vol:cz at: 3-Jul-2003 10:02


Hi all, for the ones who want to "play with fire", I wrote the functions described below. They work e.g. under Rebol/View 1.2.8. Usage: a: "1234" ; == "1234" adr: address? a get-mem? adr ; == #"1" get-mem? adr + 1 ; == #"2" get-mem? adr + 2 ; == #"3" get-mem? adr + 3 ; == #"4" get-mem? adr + 4 ; == #"^@" set-mem adr + 1 #"a" ; == #"a" a ; == "1a34" address?: function [ {get the address of a string} s [any-string!] ] [address] [ s: make struct! [s [string!]] reduce [s] address: make struct! [i [integer!]] none change third address third s address/i ] get-mem?: function [ {get the byte from a memory address} address [integer!] ] [m] [ address: make struct! [i [integer!]] reduce [address] m: make struct! [c [struct! [chr [char!]]]] none change third m third address m/c/chr ] set-mem: function [ {set a byte at a specific memory address} address [integer!] value [char!] ] [m] [ address: make struct! [i [integer!]] reduce [address] m: make struct! [c [struct! [chr [char!]]]] none change third m third address m/c/chr: value ] -L

 [11/18] from: cyphre:seznam:cz at: 3-Jul-2003 10:33


Hi Ladislav, Thanks for those handy functions! I think they should be a part of /View function set. Cyphre ----- Original Message ----- From: "Ladislav Mecir" <[lmecir--mbox--vol--cz]> To: <[rebol-list--rebol--com]> Sent: Thursday, July 03, 2003 10:02 AM Subject: [REBOL] Re: External library interface Hi all, for the ones who want to "play with fire", I wrote the functions described below. They work e.g. under Rebol/View 1.2.8. Usage: a: "1234" ; == "1234" adr: address? a get-mem? adr ; == #"1" get-mem? adr + 1 ; == #"2" get-mem? adr + 2 ; == #"3" get-mem? adr + 3 ; == #"4" get-mem? adr + 4 ; == #"^@" set-mem adr + 1 #"a" ; == #"a" a ; == "1a34" address?: function [ {get the address of a string} s [any-string!] ] [address] [ s: make struct! [s [string!]] reduce [s] address: make struct! [i [integer!]] none change third address third s address/i ] get-mem?: function [ {get the byte from a memory address} address [integer!] ] [m] [ address: make struct! [i [integer!]] reduce [address] m: make struct! [c [struct! [chr [char!]]]] none change third m third address m/c/chr ] set-mem: function [ {set a byte at a specific memory address} address [integer!] value [char!] ] [m] [ address: make struct! [i [integer!]] reduce [address] m: make struct! [c [struct! [chr [char!]]]] none change third m third address m/c/chr: value ] -L

 [12/18] from: rotenca:telvia:it at: 3-Jul-2003 11:18


Ciao ladislav, For any-string you need: address?: function [ {get the address of a string} s [any-string!] ] [address] [ parse/all s [s:] s: make struct! [s [string!]] reduce [s] address: make struct! [i [integer!]] none change third address third s address/i ] Can we find a workaround for block (instead of string?) --- Ciao Romano

 [13/18] from: lmecir:mbox:vol:cz at: 3-Jul-2003 12:02


Hi Romano,
> For any-string you need: > address?: function [
<<quoted lines omitted: 7>>
> address/i > ]
it looks like my function is working here without modification: address? #{3131} ; == 11169128 address? [lmecir--mbox--vol--cz] ; == 11154848 address? make image! none ; == 11169336
> Can we find a workaround for block (instead of string?)
?
> Ciao > Romano
Ciao -L

 [14/18] from: rotenca:telvia:it at: 3-Jul-2003 12:47


Ciao ladislav,
>it looks like my function is working here without modification:
It does not work in the current not beta view release, but it works in 1.2.8.
>> Can we find a workaround for block (instead of string?) >?
Can we find the address of a block? --- Ciao Romano

 [15/18] from: ptretter:charter at: 3-Jul-2003 8:53


This is very nice stuff. Now if we can determine the memory address of a function in memory maybe we can take REBOL to another higher level and make an ADDRESSOF function to point at a routine! stored in memory and pass it back to external functions as a callback. Paul ----- Original Message ----- From: "Ladislav Mecir" <[lmecir--mbox--vol--cz]> To: <[rebol-list--rebol--com]> Sent: Thursday, July 03, 2003 5:02 AM Subject: [REBOL] Re: External library interface Hi Romano,
> For any-string you need: > address?: function [
<<quoted lines omitted: 7>>
> address/i > ]
it looks like my function is working here without modification: address? #{3131} ; == 11169128 address? [lmecir--mbox--vol--cz] ; == 11154848 address? make image! none ; == 11169336
> Can we find a workaround for block (instead of string?)
?
> Ciao > Romano
Ciao -L

 [16/18] from: maximo:meteorstudios at: 3-Jul-2003 10:35


thanks everyone for the memory poking code, boy would I have used it last year, when I did my scsi disk interface code ... ! It was working but I had a lot of fun getting it to work. Paul, that callback idea is great... opening rebol views from external apps... but isn't there a problem with the GC though?, if we do that? -max ----------- meteor Studios, T.D. ----------- Strong enough for a man, but made for a woman

 [17/18] from: ptretter:charter at: 3-Jul-2003 10:40


Actually, the idea is to pass a "pointer" to a callback function to an external library. My thinking is that if we can have a pointer to a routine! and pass that to an external function it could then execute that code and return whatever value we define. Look at the EnumWindows function in the Windows API for more information on what I'm talking about. There is a work around for EnumWindows that I have found but for creating services on windows - callbacks are required of which I have not found a work around. Paul ----- Original Message ----- From: "Maxim Olivier-Adlhoch" <[maximo--meteorstudios--com]> To: <[rebol-list--rebol--com]> Sent: Thursday, July 03, 2003 9:35 AM Subject: [REBOL] Re: External library interface thanks everyone for the memory poking code, boy would I have used it last year, when I did my scsi disk interface code ... ! It was working but I had a lot of fun getting it to work. Paul, that callback idea is great... opening rebol views from external apps... but isn't there a problem with the GC though?, if we do that? -max ----------- meteor Studios, T.D. ----------- Strong enough for a man, but made for a woman

 [18/18] from: antonr:iinet:au at: 4-Jul-2003 16:14


I think max is worried that the Garbage Collector will try to free the routine! or function! (or maybe move it) before it is finished being used by the external library. As long as we have a word referring to it in rebol, then rebol should leave it alone, I think. Anton.

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted