1. Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » topic index » view message » categorize

2. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

<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

new topic     » goto parent     » topic index » view message » categorize

3. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » goto parent     » topic index » view message » categorize

4. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » goto parent     » topic index » view message » categorize

5. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » goto parent     » topic index » view message » categorize

6. Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » goto parent     » topic index » view message » categorize

7. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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

new topic     » goto parent     » topic index » view message » categorize

8. Re: Wrapping DLLs in Euphoria (was: [OT] Swap RGB)

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.

blink

> 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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu