1. Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Juergen Luethje <j.lue at gmx.?e> Oct 26, 2007
- 696 views
Ricardo Forno wrote: <snip> > By the way, I don't really know how to deal with DLLs. > Where can I find an explanation? I know how to program in C, > but only at the applicaton level. I do not know any tutorial for doing this with Euphoria. However, the basic stuff -- which covers at least 80% of what I personally need -- is easy. I'll start writing some basic things. As far as more advanced stuff is concerned, and when I make mistakes or forget something, hopefully others will correct or complement the text. a) You cannot do without the documentation of the regarding DLL. b) Tell your Eu programm about the DLL and define the desired routines/variables inside the DLL. c) Use the previously defined routines/variables. ad a) Of course often it's useful to wrap API functions of the operating system. Unfortunately, I know little about Linux, so I'll write only about Windows here. I find the documentation of the Windows API somewhat unsorted. However, normally I use this as entry: Windows API Reference http://msdn2.microsoft.com/en-us/library/aa383749.aspx You'll find there documentation of API functions, and of special structures that are sometimes needed as well (say e.g. SYSTEMTIME). Some functions need special constants. Their names are mentioned in the documentation, but normally not their value. You'll find the value of most constant in the header files of your C compiler (or in some User contributions in the Eu archieves, I think). Of many Windows API functions there are 2 versions: One with an "A" at the end (e.g. "DeleteFileA", see below), and another one with a "W" at the end. "A" denotes the ANSI version, "W" denotes the Unicode version. If you want your program to be able to run on the old Windows 9x systems, then it should only wrap the "A" versions. ad b) You'll need in Euphoria: - open_dll() - define_c_func() - define_c_proc() - define_c_var() ad c) You'll need in Euphoria: - c_func() - c_proc() ... and often also: - allocate() - allocate_string() - peek() - poke() - free() The Eu documentation of all these routines is good or very good IMHO. A simple example follows:
include dll.e include machine.e include misc.e -- for constant WIN32 atom Kernel32 integer DeleteFile if platform() = WIN32 then Kernel32 = open_dll("kernel32.dll") DeleteFile = define_c_func(Kernel32, "DeleteFileA", {C_POINTER}, C_LONG) end if global function delete_file (sequence fileName) atom lpszFileName, ret if DeleteFile = -1 then return -1 -- error end if lpszFileName = allocate_string(fileName) ret = c_func(DeleteFile, {lpszFileName}) - 1 free(lpszFileName) return ret -- -1 on error end function -- Demo sequence fileName fileName = "trash.txt" if delete_file(fileName) = -1 then printf(1, "Can't delete file '%s'.", {fileName}) else printf(1, "File %s' deleted.", {fileName}) end if if getc(0) then end if
> Moreover, where can I get a description of the other routines in user32.dll? On the MSDN website, there are lists where the API functions are sorted alphabetically, or grouped by category. ATM I don't know about a list where they are grouped by DLL. But as a rough estimate, I think that functions that are in the same category often may be in the same DLL, too. > One thing that recently I wondered how is it done is how some programs > intercept the Ctrl-C call to the clipboard, and then manage to store > the clipboard contents in a file. Can this be done with some system dll? Yes, it can. If you want, I can write something like that in Euphoria. > Many thanks for your help. You are welcome! Regards, Juergen
2. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by CChris <christian.cuvier at agr?culture.g?uv.fr> Oct 26, 2007
- 640 views
<Some snippage/> > Some functions need special constants. Their names are mentioned in the > documentation, but normally not their value. You'll find the value of > most constant in the header files of your C compiler (or in some User > contributions in the Eu archieves, I think). > I often find these values by using Google and looking for two sorts of sites: 1/ VB sites, because they don't use the standard C headers, so the code posted there needs to define these constants explicitly, which is what we want to see; 2/ www.eiffel.com, and specially the documentation of WEL (roughly equvalent to win32lib, but part of the standard Windows distribution). > Of many Windows API functions there are 2 versions: One with an "A" at > the end (e.g. "DeleteFileA", see below), and another one with a "W" at > the end. "A" denotes the ANSI version, "W" denotes the Unicode version. > If you want your program to be able to run on the old Windows 9x > systems, then it should only wrap the "A" versions. > One of the scarce Eu programs I use is dsearch.exw, in the demo\win32 folder. Give it the name of a WinAPI routine, and it does a fairly decent job at finding it in existing system dll's, and reporting the Ex, A or W decoration even if you didn't supply it. You may find it useful to edit it and add winspool.drv to its dll list. Otherwise, if you look at MSDN pages, the "requirements" section at the bottom of the page will give you a .lib name, the extension of which you only need to change to .dll. > > ad b) > You'll need in Euphoria: > - open_dll() > - define_c_func() > - define_c_proc() > - define_c_var() > > > ad c) > You'll need in Euphoria: > - c_func() > - c_proc() > > ... and often also: > - allocate() > - allocate_string() > - peek() > - poke() > - free() > Beware: if you use win32lib, it also have its own set of routines, registerw32Function(), w32Func() and friends. I noticed that using both registerw32Function() and define_c_func() on the same exported routine results in c_func() calls failing. If define_c_func() is done first, everything is fine iirc. I usually avoid mixing the two types of registration. > The Eu documentation of all these routines is good or very good IMHO. > A simple example follows: > }}} <eucode> > include dll.e > include machine.e > include misc.e -- for constant WIN32 > > atom Kernel32 > integer DeleteFile > > if platform() = WIN32 then > Kernel32 = open_dll("kernel32.dll") > DeleteFile = define_c_func(Kernel32, "DeleteFileA", {C_POINTER}, C_LONG) > end if > > global function delete_file (sequence fileName) > atom lpszFileName, ret > > if DeleteFile = -1 then > return -1 -- error > end if > > lpszFileName = allocate_string(fileName) > ret = c_func(DeleteFile, {lpszFileName}) - 1 > free(lpszFileName) > return ret -- -1 on error > end function > > > -- Demo > sequence fileName > > fileName = "trash.txt" > > if delete_file(fileName) = -1 then > printf(1, "Can't delete file '%s'.", {fileName}) > else > printf(1, "File %s' deleted.", {fileName}) > end if > if getc(0) then end if > </eucode> {{{ > > > Moreover, where can I get a description of the other routines in user32.dll? > > On the MSDN website, there are lists where the API functions are sorted > alphabetically, or grouped by category. ATM I don't know about a list > where they are grouped by DLL. But as a rough estimate, I think that > functions that are in the same category often may be in the same DLL, > too. > If you use win32.hlp from the archive - it is really starting to age -, you'll notice a "Group" link in the upper bar. This links to a table of related exported names, pretty useful. For a given routine, the Quickinfo link will tell you, among other things, in which .lib (read .dll) it is. Sometimes I also use scanbin.exe (easily available on the net) to explore a dll and its dependencies. Old but useful. CChris
3. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Matt Lewis <matthewwalkerlewis at ?ma?l.com> Oct 26, 2007
- 629 views
CChris wrote: > > <Some snippage/> > > > Some functions need special constants. Their names are mentioned in the > > documentation, but normally not their value. You'll find the value of > > most constant in the header files of your C compiler (or in some User > > contributions in the Eu archieves, I think). > > I often find these values by using Google and looking for two sorts of sites: > 1/ VB sites, because they don't use the standard C headers, so the code posted > there needs to define these constants explicitly, which is what we want to > see; > 2/ www.eiffel.com, and specially the documentation of WEL (roughly equvalent > to win32lib, but part of the standard Windows distribution). If you have a compiler installed (i.e., OpenWatcom) you probably have the headers sitting on your hard drive. For me: C:\WATCOM\h\nt\ Matt
4. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Juergen Luethje <j.lue at gm?.d?> Oct 26, 2007
- 643 views
Matt Lewis wrote: > > CChris wrote: > > > > <Some snippage/> > > > > > Some functions need special constants. Their names are mentioned in the > > > documentation, but normally not their value. You'll find the value of > > > most constant in the header files of your C compiler (or in some User ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > contributions in the Eu archieves, I think). > > > > I often find these values by using Google and looking for two sorts of > > sites: > > 1/ VB sites, because they don't use the standard C headers, so the code > > posted > > there needs to define these constants explicitly, which is what we want to > > see; > > 2/ www.eiffel.com, and specially the documentation of WEL (roughly equvalent > > to win32lib, but part of the standard Windows distribution). > > If you have a compiler installed (i.e., OpenWatcom) you probably have > the headers sitting on your hard drive. For me: > > C:\WATCOM\h\nt\ That's what I was meaning, too. Regards, Juergen
5. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Matt Lewis <matthewwalkerlewis at gm?il.c?m> Oct 26, 2007
- 682 views
Juergen Luethje wrote: > > That's what I was meaning, too. Yeah, but if I won't take the time to read your post, why would anyone else? :P Matt
6. Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Juergen Luethje <j.lue at gmx.??> Oct 26, 2007
- 673 views
- Last edited Oct 27, 2007
Pete Lomax wrote: > Ricardo Forno wrote: <snip> >> One thing that recently I wondered how is it done is how some programs >> intercept the Ctrl-C call to the clipboard, and then manage to store >> the clipboard contents in a file. Can this be done with some system dll? > > JL says he can do, I wouldn't mind seeing this as well. - Run the following program. - Switch to any other programs, and copy _text_ to the clipboard by using CTRL+C one or more times. - Press ESC to terminate this program. BTW: There should be a built-in fast peek_string() function in Euphoria.
include dll.e include machine.e include misc.e --===========================[ Utilities ]============================== -- Windows API wrappers constant CF_TEXT = 1 atom User32 integer OpenClipboard_, GetClipboardData_, CloseClipboard_, GetAsyncKeyState_ if platform() = WIN32 then User32 = open_dll("user32.dll") OpenClipboard_ = define_c_func(User32, "OpenClipboard", {C_LONG}, C_LONG) GetClipboardData_ = define_c_func(User32, "GetClipboardData", {C_LONG}, C_LONG) CloseClipboard_ = define_c_func(User32, "CloseClipboard", {}, C_LONG) GetAsyncKeyState_ = define_c_func(User32, "GetAsyncKeyState", {C_LONG}, C_SHORT) end if ------------------------------------------------------------------------ -- Other utilities constant SL_CODE = allocate(26) poke(SL_CODE, { -- After the routine has pushed 4 bytes on the stack, first int -- argument is at stack offset +8. #57, -- push edi #8B, #7C, #24, #08, -- mov edi, [esp+8] #B9, #FF, #FF, #FF, #FF, -- mov ecx, #FFFFFFFF #B0, #00, -- mov al, 0 #FC, -- cld #F2, #AE, -- repne scasb #B8, #FE, #FF, #FF, #FF, -- mov eax, #FFFFFFFE #29, #C8, -- sub eax, ecx #5F, -- pop edi #C2, #04, #00 -- ret 4 -- pop 4 bytes off the stack }) constant STRLEN = define_c_func("", SL_CODE, {C_POINTER}, C_ULONG) -- Usage: -- len = c_func(STRLEN, {addr}) -- -- 'addr' is a pointer to the first character of a null-terminated -- string in memory; -- returns the length of the string in bytes (not including the -- terminating null character); -- works like the Windows API function LstrLen(), but is cross-platform function peek_string (atom addr) -- read a null-terminated string, starting at address 'addr' in memory return peek({addr, c_func(STRLEN,{addr})}) end function --=======================[ Desired functions ]========================== global function clipboard_text() sequence ret atom lpszText, void ret = "" if c_func(OpenClipboard_, {NULL}) then lpszText = c_func(GetClipboardData_, {CF_TEXT}) if lpszText then ret = peek_string(lpszText) end if void = c_func(CloseClipboard_, {}) end if return ret end function global function is_key_down (atom key) return and_bits(c_func(GetAsyncKeyState_, {key}), #8000) != 0 end function --==============================[ Demo ]================================ without warning constant VK_ESCAPE = #1B, VK_CONTROL = #11, VK_C = #43 sequence filename integer fn filename = "collection.txt" fn = open(filename, "w") if fn = -1 then printf(1, "Can't open '%s'.", {filename}) if getc(0) then end if abort(1) end if while not is_key_down(VK_ESCAPE) do -- ESC terminates the program if is_key_down(VK_CONTROL) and is_key_down(VK_C) then -- Ctrl+C sleep(1) puts(fn, clipboard_text() & "\n") end if end while close(fn)
Regards, Juergen
7. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Pete Lomax <petelomax at bluey?nder.c?.uk> Oct 27, 2007
- 628 views
Juergen Luethje wrote: > > - Run the following program. > - Switch to any other programs, and copy _text_ to the clipboard > by using CTRL+C one or more times. Thanks, it works exactly as advertised. However it doesn't work when you right click and select Copy. I didn't know about GetAsyncKeyState, when I looked it up I stumbled across SetClipboardViewer, I might try doing something with that. > BTW: There should be a built-in fast peek_string() function in Euphoria. LOL. Including this, Edita just showed me no less than 31 versions of that lying around on my disk, most duplicates, 4 distinct. If I get round to it, I'll time trial them against a fast asm version sometime next week and let you know the results. Regards, Pete
8. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)
- Posted by Juergen Luethje <j.lue at gmx?d?> Oct 27, 2007
- 666 views
Pete Lomax wrote: > Juergen Luethje wrote: > > > > - Run the following program. > > - Switch to any other programs, and copy _text_ to the clipboard > > by using CTRL+C one or more times. > Thanks, it works exactly as advertised. > However it doesn't work when you right click and select Copy. This is true. Because Richardo wrote about Ctrl+C, I focussed on that. According to my habits, I personnally never use Ctrl+C, but I use Ctrl+Insert instead. The program does not work with Ctrl+Insert, too. The program was just a proof-of-concept. However, in a real program users might take advantage of such a difference: They use Ctrl+C in order to copy text to the clipboard that shall also be written to the regarding file, and use Ctrl+Insert or right click and select Copy for textb that shall only be copied to the clipboard. Anyway, at the end of this post there is another program, that should work with any method of putting text on the clipboard. > I didn't know about GetAsyncKeyState, when I looked it up I stumbled across > SetClipboardViewer, I might try doing something with that. I recently stumbled across SetClipboardViewer(), too. And I also think that it's interesting. > > BTW: There should be a built-in fast peek_string() function in Euphoria. > LOL. Including this, Edita just showed me no less than 31 versions of that > lying > around on my disk, most duplicates, 4 distinct. > If I get round to it, I'll time > trial them against a fast asm version sometime next week and let you know the > results. Yes, please. That would be interesting for me. Here is another program for writing text, that was copied to the clipboard, automagically to a file. Please note that in contrast to the previous version, GetAsyncKeyState() is not actually needed here. It's only used here to provide a simple possibility for terminating the program.
include dll.e include machine.e include misc.e --===========================[ Utilities ]============================== -- Windows API wrappers constant CF_TEXT = 1 atom User32 integer OpenClipboard_, GetClipboardData_, CloseClipboard_, GetClipboardSequenceNumber_, GetAsyncKeyState_ if platform() = WIN32 then User32 = open_dll("user32.dll") OpenClipboard_ = define_c_func(User32, "OpenClipboard", {C_LONG}, C_LONG) GetClipboardData_ = define_c_func(User32, "GetClipboardData", {C_LONG}, C_LONG) CloseClipboard_ = define_c_func(User32, "CloseClipboard", {}, C_LONG) GetClipboardSequenceNumber_ = define_c_func(User32, "GetClipboardSequenceNumber", {}, C_ULONG) GetAsyncKeyState_ = define_c_func(User32, "GetAsyncKeyState", {C_LONG}, C_SHORT) end if ------------------------------------------------------------------------ -- Other utilities constant SL_CODE = allocate(26) poke(SL_CODE, { -- After the routine has pushed 4 bytes on the stack, first int -- argument is at stack offset +8. #57, -- push edi #8B, #7C, #24, #08, -- mov edi, [esp+8] #B9, #FF, #FF, #FF, #FF, -- mov ecx, #FFFFFFFF #B0, #00, -- mov al, 0 #FC, -- cld #F2, #AE, -- repne scasb #B8, #FE, #FF, #FF, #FF, -- mov eax, #FFFFFFFE #29, #C8, -- sub eax, ecx #5F, -- pop edi #C2, #04, #00 -- ret 4 -- pop 4 bytes off the stack }) constant STRLEN = define_c_func("", SL_CODE, {C_POINTER}, C_ULONG) -- Usage: -- len = c_func(STRLEN, {addr}) -- -- 'addr' is a pointer to the first character of a null-terminated -- string in memory; -- returns the length of the string in bytes (not including the -- terminating null character); -- works like the Windows API function LstrLen(), but is cross-platform function peek_string (atom addr) -- read a null-terminated string, starting at address 'addr' in memory return peek({addr, c_func(STRLEN,{addr})}) end function --=========================[ Used functions ]=========================== global function clipboard_text() sequence ret atom lpszText, void ret = "" if c_func(OpenClipboard_, {NULL}) then lpszText = c_func(GetClipboardData_, {CF_TEXT}) if lpszText then ret = peek_string(lpszText) end if void = c_func(CloseClipboard_, {}) end if return ret end function global function is_key_down (atom key) return and_bits(c_func(GetAsyncKeyState_, {key}), #8000) != 0 end function --==============================[ Demo ]================================ constant VK_ESCAPE = #1B sequence filename, text atom clipNumber integer fn filename = "collection.txt" fn = open(filename, "w") if fn = -1 then printf(1, "Can't open '%s'.", {filename}) if getc(0) then end if abort(1) end if clipNumber = c_func(GetClipboardSequenceNumber_, {}) while not is_key_down(VK_ESCAPE) do if clipNumber != c_func(GetClipboardSequenceNumber_, {}) then clipNumber = c_func(GetClipboardSequenceNumber_, {}) text = clipboard_text() if length(text) then puts(fn, text & "\n") end if end if end while close(fn)
Regards, Juergen