Up | TOC | Index | |||||
<< 7 Included Tools | < 8.38 URL handling | Up: 8 API Reference | 8.40 Errors and Warnings > | 9 Release Notes >> |
8.39 Dynamic Linking to external code
8.39.1 C Type Constants
These C type constants are used when defining external C functions in a shared library file.
Example 1:
See define_c_proc
See Also:
define_c_proc, define_c_func, define_c_var
8.39.1.1 C_CHAR
include std/dll.e namespace dll public constant C_CHAR
char 8-bits
8.39.1.2 C_BYTE
include std/dll.e namespace dll public constant C_BYTE
byte 8-bits
8.39.1.3 C_UCHAR
include std/dll.e namespace dll public constant C_UCHAR
unsigned char 8-bits
8.39.1.4 C_UBYTE
include std/dll.e namespace dll public constant C_UBYTE
ubyte 8-bits
8.39.1.5 C_SHORT
include std/dll.e namespace dll public constant C_SHORT
short 16-bits
8.39.1.6 C_WORD
include std/dll.e namespace dll public constant C_WORD
word 16-bits
8.39.1.7 C_USHORT
include std/dll.e namespace dll public constant C_USHORT
unsigned short 16-bits
8.39.1.8 C_INT
include std/dll.e namespace dll public constant C_INT
int 32-bits
8.39.1.9 C_BOOL
include std/dll.e namespace dll public constant C_BOOL
bool 32-bits
8.39.1.10 C_UINT
include std/dll.e namespace dll public constant C_UINT
unsigned int 32-bits
8.39.1.11 C_SIZE_T
include std/dll.e namespace dll public constant C_SIZE_T
size_t 32-bits
8.39.1.12 C_LONG
include std/dll.e namespace dll public constant C_LONG
long 32-bits
8.39.1.13 C_ULONG
include std/dll.e namespace dll public constant C_ULONG
unsigned long 32-bits
8.39.1.14 C_POINTER
include std/dll.e namespace dll public constant C_POINTER
any valid pointer 32-bits
8.39.1.15 C_HANDLE
include std/dll.e namespace dll public constant C_HANDLE
handle 32-bits
8.39.1.16 C_HWND
include std/dll.e namespace dll public constant C_HWND
hwnd 32-bits
8.39.1.17 C_DWORD
include std/dll.e namespace dll public constant C_DWORD
dword 32-bits
8.39.1.18 C_WPARAM
include std/dll.e namespace dll public constant C_WPARAM
wparam 32-bits
8.39.1.19 C_LPARAM
include std/dll.e namespace dll public constant C_LPARAM
lparam 32-bits
8.39.1.20 C_HRESULT
include std/dll.e namespace dll public constant C_HRESULT
hresult 32-bits
8.39.1.21 C_FLOAT
include std/dll.e namespace dll public constant C_FLOAT
float 32-bits
8.39.1.22 C_DOUBLE
include std/dll.e namespace dll public constant C_DOUBLE
double 64-bits
8.39.1.23 C_DWORDLONG
include std/dll.e namespace dll public constant C_DWORDLONG
dwordlong 64-bits
8.39.2 External Euphoria Type Constants
These are used for arguments to and the return value from a Euphoria shared library file (.dll, .so or .dylib).
8.39.2.1 E_INTEGER
include std/dll.e namespace dll public constant E_INTEGER
integer
8.39.2.2 E_ATOM
include std/dll.e namespace dll public constant E_ATOM
atom
8.39.2.3 E_SEQUENCE
include std/dll.e namespace dll public constant E_SEQUENCE
sequence
8.39.2.4 E_OBJECT
include std/dll.e namespace dll public constant E_OBJECT
object
8.39.3 Constants
8.39.3.1 NULL
include std/dll.e namespace dll public constant NULL
C's NULL pointer
8.39.4 Routines
8.39.4.1 open_dll
include std/dll.e namespace dll public function open_dll(sequence file_name)
Open a Windows dynamic link library (.dll) file, or a Unix shared library (.so) file.
Parameters:
- file_name : a sequence, the name of the shared library to open or a sequence of filename's to try to open.
Returns:
An atom, actually a 32-bit address. 0 is returned if the .dll can't be found.
Errors:
The length of file_name (or any filename contained therein) should not exceed 1,024 characters.
Comments:
file_name can be a relative or an absolute file name. Most operating systems will use the normal search path for locating non-relative files.
file_name can be a list of file names to try. On different Linux platforms especially, the filename will not always be the same. For instance, you may wish to try opening libmylib.so, libmylib.so.1, libmylib.so.1.0, libmylib.so.1.0.0. If given a sequence of file names to try, the first successful library loaded will be returned. If no library could be loaded, 0 will be returned after exhausting the entire list of file names.
The value returned by open_dll() can be passed to define_c_proc(), define_c_func(), or define_c_var().
You can open the same .dll or .so file multiple times. No extra memory is used and you'll get the same number returned each time.
Euphoria will close the .dll/.so for you automatically at the end of execution.
Example 1:
atom user32 user32 = open_dll("user32.dll") if user32 = 0 then puts(1, "Couldn't open user32.dll!\n") end if
Example 2:
atom mysql_lib mysql_lib = open_dll({"libmysqlclient.so", "libmysqlclient.so.15", "libmysqlclient.so.15.0"}) if mysql_lib = 0 then puts(1, "Couldn't find the mysql client library\n") end if
See Also:
define_c_func, define_c_proc, define_c_var, c_func, c_proc
8.39.4.2 define_c_var
include std/dll.e namespace dll public function define_c_var(atom lib, sequence variable_name)
Gets the address of a symbol in a shared library or in RAM.
Parameters:
- lib : an atom, the address of a Linux or FreeBSD shared library, or Windows .dll, as returned by open_dll().
- variable_name : a sequence, the name of a public C variable defined within the library.
Returns:
An atom, the memory address of variable_name.
Comments:
Once you have the address of a C variable, and you know its type, you can use peek() and poke() to read or write the value of the variable. You can in the same way obtain the address of a C function and pass it to any external routine that requires a callback address.
Example:
see euphoria/demo/linux/mylib.ex
See Also:
c_proc, define_c_func, c_func, open_dll
8.39.4.3 define_c_proc
include std/dll.e namespace dll public function define_c_proc(object lib, object routine_name, sequence arg_types)
Define the characteristics of either a C function, or a machine-code routine that you wish to call as a procedure from your Euphoria program.
Parameters:
- lib : an object, either an entry point returned as an atom by open_dll(), or "" to denote a routine the RAM address is known.
- routine_name : an object, either the name of a procedure in a shared object or the machine address of the procedure.
- argtypes : a sequence of type constants.
Returns:
A small integer, known as a routine id, will be returned.
Errors:
The length of name should not exceed 1,024 characters.
Comments:
Use the returned routine id as the first argument to c_proc() when you wish to call the routine from Euphoria.
A returned value of -1 indicates that the procedure could not be found or linked to.
On Windows, you can add a '+' character as a prefix to the procedure name. This tells Euphoria that the function uses the cdecl calling convention. By default, Euphoria assumes that C routines accept the stdcall convention.
When defining a machine code routine, lib must be the empty sequence, "" or {}, and routine_name indicates the address of the machine code routine. You can poke the bytes of machine code into a block of memory reserved using allocate(). On Windows, the machine code routine is normally expected to follow the stdcall calling convention, but if you wish to use the cdecl convention instead, you can code {'+', address} instead of address.
argtypes is made of type constants, which describe the C types of arguments to the procedure. They may be used to define machine code parameters as well.
The C function that you define could be one created by the Euphoria To C Translator, in which case you can pass Euphoria data to it, and receive Euphoria data back. A list of Euphoria types is shown above.
You can pass any C integer type or pointer type. You can also pass a Euphoria atom as a C double or float.
Parameter types which use 4 bytes or less are all passed the same way, so it is not necessary to be exact.
Currently, there is no way to pass a C structure by value. You can only pass a pointer to a structure. However, you can pass a 64 bit integer by pretending to pass two C_LONG instead. When calling the routine, pass low doubleword first, then high doubleword.
The C function can return a value but it will be ignored. If you want to use the value returned by the C function, you must instead define it with define_c_func() and call it with c_func().
Example 1:
atom user32 integer ShowWindow -- open user32.dll - it contains the ShowWindow C function user32 = open_dll("user32.dll") -- It has 2 parameters that are both C int. ShowWindow = define_c_proc(user32, "ShowWindow", {C_INT, C_INT}) -- If ShowWindow used the cdecl convention, -- we would have coded "+ShowWindow" here if ShowWindow = -1 then puts(1, "ShowWindow not found!\n") end if
See Also:
c_proc, define_c_func, c_func, open_dll
8.39.4.4 define_c_func
include std/dll.e namespace dll public function define_c_func(object lib, object routine_name, sequence arg_types, atom return_type)
Define the characteristics of either a C function, or a machine-code routine that returns a value.
Parameters:
- lib : an object, either an entry point returned as an atom by open_dll(), or "" to denote a routine the RAM address is known.
- routine_name : an object, either the name of a procedure in a shared object or the machine address of the procedure.
- argtypes : a sequence of type constants.
- return_type : an atom, indicating what type the function will return.
Returns:
A small integer, known as a routine id, will be returned.
Errors:
The length of name should not exceed 1,024 characters.
Comments:
Use the returned routine id as the first argument to c_proc() when you wish to call the routine from Euphoria.
A returned value of -1 indicates that the procedure could not be found or linked to.
On Windows, you can add a '+' character as a prefix to the function name. This indicates to Euphoria that the function uses the cdecl calling convention. By default, Euphoria assumes that C routines accept the stdcall convention.
When defining a machine code routine, x1 must be the empty sequence, "" or {}, and x2 indicates the address of the machine code routine. You can poke the bytes of machine code into a block of memory reserved using allocate(). On Windows, the machine code routine is normally expected to follow the stdcall calling convention, but if you wish to use the cdecl convention instead, you can code {'+', address} instead of address for x2.
The C function that you define could be one created by the Euphoria To C Translator, in which case you can pass Euphoria data to it, and receive Euphoria data back. A list of Euphoria types is contained in dll.e:
- E_INTEGER = #06000004
- E_ATOM = #07000004
- E_SEQUENCE= #08000004
- E_OBJECT = #09000004
You can pass or return any C integer type or pointer type. You can also pass a Euphoria atom as a C double or float, and get a C double or float returned to you as a Euphoria atom.
Parameter types which use 4 bytes or less are all passed the same way, so it is not necessary to be exact when choosing a 4-byte parameter type. However the distinction between signed and unsigned may be important when you specify the return type of a function.
Currently, there is no way to pass a C structure by value or get a C structure as a return result. You can only pass a pointer to a structure and get a pointer to a structure as a result. However, you can pass a 64 bit integer as two C_LONG instead. On calling the routine, pass low doubleword first, then high doubleword.
If you are not interested in using the value returned by the C function, you should instead define it with define_c_proc() and call it with c_proc().
If you use euiw to call a cdecl C routine that returns a floating-point value, it might not work. This is because the Watcom C compiler (used to build euiw) has a non-standard way of handling cdecl floating-point return values.
Passing floating-point values to a machine code routine will be faster if you use c_func() rather than call() to call the routine, since you won't have to use atom_to_float64() and poke() to get the floating-point values into memory.
Example 1:
atom user32 integer LoadIcon -- open user32.dll - it contains the LoadIconA C function user32 = open_dll("user32.dll") -- It takes a C pointer and a C int as parameters. -- It returns a C int as a result. LoadIcon = define_c_func(user32, "LoadIconA", {C_POINTER, C_INT}, C_INT) -- We use "LoadIconA" here because we know that LoadIconA -- needs the stdcall convention, as do -- all standard .dll routines in the WINDOWS API. -- To specify the cdecl convention, we would have used "+LoadIconA". if LoadIcon = -1 then puts(1, "LoadIconA could not be found!\n") end if
See Also:
demo\callmach.ex, c_func, define_c_proc, c_proc, open_dll
8.39.4.5 c_func
<built-in> function c_func(integer rid, sequence args={})
Call a C function, or machine code function, or translated/compiled Euphoria function by routine id.
Parameters:
- rid : an integer, the routine_id of the external function being called.
- args : a sequence, the list of parameters to pass to the function
Returns:
An object, whose type and meaning was defined on calling define_c_func().
Errors:
If rid is not a valid routine id, or the arguments do not match the prototype of the routine being called, an error occurs.
Comments:
rid must have been returned by define_c_func(), not by routine_id(). The type checks are different, and you would get a machine level exception in the best case.
If the function does not take any arguments then args should be {}.
If you pass an argument value which contains a fractional part, where the C function expects a C integer type, the argument will be rounded towards 0. e.g. 5.9 will be passed as 5, -5.9 will be passed as -5.
The function could be part of a .dll or .so created by the Euphoria To C Translator. In this case, a Euphoria atom or sequence could be returned. C and machine code functions can only return integers, or more generally, atoms (IEEE floating-point numbers).
Example 1:
atom user32, hwnd, ps, hdc integer BeginPaint -- open user32.dll - it contains the BeginPaint C function user32 = open_dll("user32.dll") -- the C function BeginPaint takes a C int argument and -- a C pointer, and returns a C int as a result: BeginPaint = define_c_func(user32, "BeginPaint", {C_INT, C_POINTER}, C_INT) -- call BeginPaint, passing hwnd and ps as the arguments, -- hdc is assigned the result: hdc = c_func(BeginPaint, {hwnd, ps})
See Also:
c_proc, define_c_proc, open_dll, Platform-Specific Issues
8.39.4.6 c_proc
<built-in> procedure c_proc(integer rid, sequence args={})
Call a C void function, or machine code function, or translated/compiled Euphoria procedure by routine id.
Parameters:
- rid : an integer, the routine_id of the external function being called.
- args : a sequence, the list of parameters to pass to the function
Errors:
If rid is not a valid routine id, or the arguments do not match the prototype of the routine being called, an error occurs.
Comments:
rid must have been returned by define_c_proc(), not by routine_id(). The type checks are different, and you would get a machine level exception in the best case.
If the procedure does not take any arguments then args should be {}.
If you pass an argument value which contains a fractional part, where the C void function expects a C integer type, the argument will be rounded towards 0. e.g. 5.9 will be passed as 5, -5.9 will be passed as -5.
Example 1:
atom user32, hwnd, rect integer GetClientRect -- open user32.dll - it contains the GetClientRect C function user32 = open_dll("user32.dll") -- GetClientRect is a VOID C function that takes a C int -- and a C pointer as its arguments: GetClientRect = define_c_proc(user32, "GetClientRect", {C_INT, C_POINTER}) -- pass hwnd and rect as the arguments c_proc(GetClientRect, {hwnd, rect})
See Also:
c_func, define_c_func, open_dll, Platform-Specific Issues
8.39.4.7 call_back
include std/dll.e namespace dll public function call_back(object id)
Get a machine address for an Euphoria procedure.
Parameters:
- id : an object, either the id returned by routine_id for the function/procedure, or a pair {'+', id}.
Returns:
An atom, the address of the machine code of the routine. It can be used by Windows, or an external C routine in a Windows .dll or Unix-like shared library (.so), as a 32-bit "call-back" address for calling your Euphoria routine.
Errors:
The length of name should not exceed 1,024 characters.
Comments:
By default, your routine will work with the stdcall convention. On Windows, you can specify its id as {'+', id}, in which case it will work with the cdecl calling convention instead. On non-Microsoft platforms, you should only use simple IDs, as there is just one standard calling convention, i.e. cdecl.
You can set up as many call-back functions as you like, but they must all be Euphoria functions (or types) with 0 to 9 arguments. If your routine has nothing to return (it should really be a procedure), just return 0 (say), and the calling C routine can ignore the result.
When your routine is called, the argument values will all be 32-bit unsigned (positive) values. You should declare each parameter of your routine as atom, unless you want to impose tighter checking. Your routine must return a 32-bit integer value.
You can also use a call-back address to specify a Euphoria routine as an exception handler in the Linux/FreeBSD signal() function. For example, you might want to catch the SIGTERM signal, and do a graceful shutdown. Some Web hosts send a SIGTERM to a CGI process that has used too much CPU time.
A call-back routine that uses the cdecl convention and returns a floating-point result, might not work with euiw. This is because the Watcom C compiler (used to build euiw) has a non-standard way of handling cdecl floating-point return values.
Example 1:
See: demo\win32\window.exw, demo\linux\qsort.ex
See Also: