COVERAGE SUMMARY
FILE SUMMARY
NameExecutedRoutines%ExecutedLines%Unexecuted
/home/matt/eu/rds/include/std/dll.e55100.00%515396.23%2
ROUTINE SUMMARY
RoutineExecutedLinesUnexecuted
define_c_proc()3475.00%1
open_dll()8988.89%1
call_back()22100.00%0
define_c_func()44100.00%0
define_c_var()22100.00%0
LINE COVERAGE DETAIL
#Executed
1
-- (c) Copyright - See License.txt
2
--****
3
-- == Dynamic Linking to external code
4
--
5
-- <>
6
--
7
namespace dll
8
9
include std/convert.e
10
include std/machine.e
11
include std/math.e
12
include std/error.e
13
include std/types.e
14
15
--****
16
-- === C Type Constants
17
-- These C type constants are used when defining external C functions in a shared
18
-- library file.
19
--
20
-- Example 1:
21
-- See [[:define_c_proc]]
22
--
23
-- See Also:
24
-- [[:define_c_proc]], [[:define_c_func]], [[:define_c_var]]
25
26
public constant
27
--** char 8-bits
28101
C_CHAR = #01000001,
29
--** byte 8-bits
30101
C_BYTE = #01000001,
31
--** unsigned char 8-bits
32101
C_UCHAR = #02000001,
33
--** ubyte 8-bits
34101
C_UBYTE = #02000001,
35
--** short 16-bits
36101
C_SHORT = #01000002,
37
--** word 16-bits
38101
C_WORD = #01000002,
39
--** unsigned short 16-bits
40101
C_USHORT = #02000002,
41
--** int 32-bits
42101
C_INT = #01000004,
43
--** bool 32-bits
44101
C_BOOL = C_INT,
45
--** unsigned int 32-bits
46101
C_UINT = #02000004,
47
--** size_t 32-bits
48101
C_SIZE_T = C_UINT,
49
--** long 32-bits
50101
C_LONG = C_INT,
51
--** unsigned long 32-bits
52101
C_ULONG = C_UINT,
53
--** any valid pointer 32-bits
54101
C_POINTER = C_UINT,
55
--** handle 32-bits
56101
C_HANDLE = C_UINT,
57
--** hwnd 32-bits
58101
C_HWND = C_UINT,
59
--** dword 32-bits
60101
C_DWORD = C_UINT,
61
--** wparam 32-bits
62101
C_WPARAM = C_LONG,
63
--** lparam 32-bits
64101
C_LPARAM = C_LONG,
65
--** hresult 32-bits
66101
C_HRESULT = C_LONG,
67
--** float 32-bits
68101
C_FLOAT = #03000004,
69
--** double 64-bits
70101
C_DOUBLE = #03000008,
71
--** dwordlong 64-bits
72101
C_DWORDLONG = #03000008,
73
$
74
75
--****
76
-- === External Euphoria Type Constants
77
-- These are used for arguments to and the return value from a Euphoria shared
78
-- library file (.dll, .so or .dylib).
79
80
public constant
81
--** integer
82101
E_INTEGER = #06000004,
83
--** atom
84101
E_ATOM = #07000004,
85
--** sequence
86101
E_SEQUENCE= #08000004,
87
--** object
88101
E_OBJECT = #09000004
89
90
91
--****
92
-- === Constants
93
94
--**
95
-- C's NULL pointer
96
97101
public constant NULL = 0
98
99101
constant M_OPEN_DLL = 50,
100101
M_DEFINE_C = 51,
101101
M_DEFINE_VAR = 56
102
103
--****
104
-- === Routines
105
--
106
107
--**
108
-- Open a Windows dynamic link library (.dll) file, or a //Unix// shared library
109
-- (.so) file.
110
--
111
-- Parameters:
112
-- # ##file_name## : a sequence, the name of the shared library to open or a sequence of filename's
113
-- to try to open.
114
--
115
-- Returns:
116
-- An **atom**, actually a 32-bit address. 0 is returned if the .dll can't be found.
117
--
118
-- Errors:
119
-- The length of ##file_name## (or any filename contained therein) should not exceed
120
-- 1,024 characters.
121
--
122
-- Comments:
123
-- ##file_name## can be a relative or an absolute file name. Most operating systems will use
124
-- the normal search path for locating non-relative files.
125
--
126
-- ##file_name## can be a list of file names to try. On different Linux platforms especially,
127
-- the filename will not always be the same. For instance, you may wish to try opening
128
-- libmylib.so, libmylib.so.1, libmylib.so.1.0, libmylib.so.1.0.0. If given a sequence of
129
-- file names to try, the first successful library loaded will be returned. If no library
130
-- could be loaded, 0 will be returned after exhausting the entire list of file names.
131
--
132
-- The value returned by ##open_dll##() can be passed to ##define_c_proc##(), ##define_c_func##(),
133
-- or ##define_c_var##().
134
--
135
-- You can open the same .dll or .so file multiple times. No extra memory is used and you'll
136
-- get the same number returned each time.
137
--
138
-- Euphoria will close the .dll/.so for you automatically at the end of execution.
139
--
140
-- Example 1:
141
--
142
-- atom user32
143
-- user32 = open_dll("user32.dll")
144
-- if user32 = 0 then
145
-- puts(1, "Couldn't open user32.dll!\n")
146
-- end if
147
--
148
--
149
-- Example 2:
150
--
151
-- atom mysql_lib
152
-- mysql_lib = open_dll({"libmysqlclient.so", "libmysqlclient.so.15", "libmysqlclient.so.15.0"})
153
-- if mysql_lib = 0 then
154
-- puts(1, "Couldn't find the mysql client library\n")
155
-- end if
156
--
157
--
158
-- See Also:
159
-- [[:define_c_func]], [[:define_c_proc]], [[:define_c_var]], [[:c_func]], [[:c_proc]]
160
161307
162307
if length(file_name) > 0 and string(file_name) then
1630
return machine_func(M_OPEN_DLL, file_name)
164
end if
165
166
-- We have a list of filenames to try, try each one, when one succeeds
167
-- abort the search and return it's value
168307
for idx = 1 to length(file_name) do
16915
atom fh = machine_func(M_OPEN_DLL, file_name[idx])
17015
if not fh = 0 then
1713
return fh
172
end if
17312
end for
174
175304
return 0
176
end function
177
178
--**
179
-- Gets the address of a symbol in a shared library or in RAM.
180
--
181
-- Parameters:
182
-- # ##lib## : an atom, the address of a Linux or FreeBSD shared library, or Windows .dll, as returned by open_dll().
183
-- # ##variable_name## : a sequence, the name of a public C variable defined within the library.
184
--
185
-- Returns:
186
-- An **atom**, the memory address of ##variable_name##.
187
--
188
-- Comments:
189
-- Once you have the address of a C variable, and you know its type, you can use ##peek##()
190
-- and ##poke##() to read or write the value of the variable. You can in the same way obtain
191
-- the address of a C function and pass it to any external routine that requires a callback address.
192
--
193
-- Example:
194
-- see ##euphoria/demo/linux/mylib.ex##
195
--
196
-- See Also:
197
-- [[:c_proc]], [[:define_c_func]], [[:c_func]], [[:open_dll]]
198
1992
2002
return machine_func(M_DEFINE_VAR, {lib, variable_name})
201
end function
202
203
--**
204
-- Define the characteristics of either a C function, or a machine-code routine that you
205
-- wish to call as a procedure from your Euphoria program.
206
--
207
-- Parameters:
208
-- # ##lib## : an object, either an entry point returned as an atom by [[:open_dll]](), or "" to denote a routine the RAM address is known.
209
-- # ##routine_name## : an object, either the name of a procedure in a shared object or the machine address of the procedure.
210
-- # ##argtypes## : a sequence of type constants.
211
--
212
-- Returns:
213
-- A small **integer**, known as a routine id, will be returned.
214
--
215
-- Errors:
216
-- The length of ##name## should not exceed 1,024 characters.
217
--
218
-- Comments:
219
-- Use the returned routine id as the first argument to [[:c_proc]]() when
220
-- you wish to call the routine from Euphoria.
221
--
222
-- A returned value of -1 indicates that the procedure could not be found or linked to.
223
--
224
-- On Windows, you can add
225
-- a '+' character as a prefix to the procedure name. This tells Euphoria that the function
226
-- uses the cdecl calling convention. By default, Euphoria assumes that C routines accept
227
-- the stdcall convention.
228
--
229
-- When defining a machine code routine, ##lib## must be the empty sequence, "" or {}, and ##routine_name##
230
-- indicates the address of the machine code routine. You can poke the bytes of machine code
231
-- into a block of memory reserved using allocate(). On Windows, the machine code routine is
232
-- normally expected to follow the stdcall calling convention, but if you wish to use the
233
-- cdecl convention instead, you can code {'+', address} instead of address.
234
--
235
-- ##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.
236
--
237
-- The C function that you define could be one created by the Euphoria To C Translator, in
238
-- which case you can pass Euphoria data to it, and receive Euphoria data back. A list of
239
-- Euphoria types is shown above.
240
--
241
-- You can pass any C integer type or pointer type. You can also pass a Euphoria atom as
242
-- a C double or float.
243
--
244
-- Parameter types which use 4 bytes or less are all passed the same way, so it is not
245
-- necessary to be exact.
246
--
247
-- Currently, there is no way to pass a C structure by value. You can only pass a pointer
248
-- 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.
249
--
250
-- The C function can return a value but it will be ignored. If you want to use the value
251
-- returned by the C function, you must instead define it with [[:define_c_func()]] and call it
252
-- with [[:c_func]]().
253
--
254
-- Example 1:
255
--
256
-- atom user32
257
-- integer ShowWindow
258
--
259
-- -- open user32.dll - it contains the ShowWindow C function
260
-- user32 = open_dll("user32.dll")
261
--
262
-- -- It has 2 parameters that are both C int.
263
-- ShowWindow = define_c_proc(user32, "ShowWindow", {C_INT, C_INT})
264
-- -- If ShowWindow used the cdecl convention,
265
-- -- we would have coded "+ShowWindow" here
266
--
267
-- if ShowWindow = -1 then
268
-- puts(1, "ShowWindow not found!\n")
269
-- end if
270
--
271
--
272
-- See Also:
273
-- [[:c_proc]], [[:define_c_func]], [[:c_func]], [[:open_dll]]
274
2751
276
sequence arg_types)
2771
if atom(routine_name) and not safe_address(routine_name, 1, A_EXECUTE) then
2780
crash("A C function is being defined from Non-executable memory.")
279
end if
2801
return machine_func(M_DEFINE_C, {lib, routine_name, arg_types, 0})
281
end function
282
283
--**
284
-- Define the characteristics of either a C function, or a machine-code routine that returns
285
-- a value.
286
--
287
-- Parameters:
288
-- # ##lib## : an object, either an entry point returned as an atom by [[:open_dll]](), or "" to denote a routine the RAM address is known.
289
-- # ##routine_name## : an object, either the name of a procedure in a shared object or the machine address of the procedure.
290
-- # ##argtypes## : a sequence of type constants.
291
-- # ##return_type## : an atom, indicating what type the function will return.
292
--
293
-- Returns:
294
-- A small **integer**, known as a routine id, will be returned.
295
--
296
-- Errors:
297
-- The length of ##name## should not exceed 1,024 characters.
298
--
299
-- Comments:
300
-- Use the returned routine id as the first argument to [[:c_proc]]() when
301
-- you wish to call the routine from Euphoria.
302
--
303
-- A returned value of -1 indicates that the procedure could not be found or linked to.
304
--
305
-- On Windows, you can add a
306
-- '+' character as a prefix to the function name. This indicates to Euphoria that the
307
-- function uses the cdecl calling convention. By default, Euphoria assumes that C routines
308
-- accept the stdcall convention.
309
--
310
-- When defining a machine code routine, x1 must be the empty sequence, "" or {}, and x2
311
-- indicates the address of the machine code routine. You can poke the bytes of machine code
312
-- into a block of memory reserved using ##allocate##(). On Windows, the machine code routine is
313
-- normally expected to follow the stdcall calling convention, but if you wish to use the
314
-- cdecl convention instead, you can code {'+', address} instead of address for x2.
315
--
316
--The C function that you define could be one created by the Euphoria To C Translator, in
317
-- which case you can pass Euphoria data to it, and receive Euphoria data back. A list of
318
-- Euphoria types is contained in dll.e:
319
--
320
-- * E_INTEGER = #06000004
321
-- * E_ATOM = #07000004
322
-- * E_SEQUENCE= #08000004
323
-- * E_OBJECT = #09000004
324
--
325
-- You can pass or return any C integer type or pointer type. You can also pass a Euphoria
326
-- atom as a C double or float, and get a C double or float returned to you as a Euphoria atom.
327
--
328
-- Parameter types which use 4 bytes or less are all passed the same way, so it is not
329
-- necessary to be exact when choosing a 4-byte parameter type. However the distinction
330
-- between signed and unsigned may be important when you specify the return type of a function.
331
--
332
-- Currently, there is no way to pass a C structure by value or get a C structure as a return
333
-- result. You can only pass a pointer to a structure and get a pointer to a structure as a
334
-- 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.
335
--
336
-- If you are not interested in using the value returned by the C function, you should
337
-- instead define it with [[:define_c_proc]]() and call it with [[:c_proc]]().
338
--
339
-- If you use euiw to call a cdecl C routine that returns a floating-point value, it might not
340
-- work. This is because the Watcom C compiler (used to build euiw) has a non-standard way of
341
-- handling cdecl floating-point return values.
342
--
343
-- Passing floating-point values to a machine code routine will be faster if you use
344
-- ##c_func##() rather than ##call##() to call the routine, since you won't have to use
345
-- ##atom_to_float64##() and ##poke##() to get the floating-point values into memory.
346
--
347
-- Example 1:
348
--
349
-- atom user32
350
-- integer LoadIcon
351
--
352
-- -- open user32.dll - it contains the LoadIconA C function
353
-- user32 = open_dll("user32.dll")
354
--
355
-- -- It takes a C pointer and a C int as parameters.
356
-- -- It returns a C int as a result.
357
-- LoadIcon = define_c_func(user32, "LoadIconA",
358
-- {C_POINTER, C_INT}, C_INT)
359
-- -- We use "LoadIconA" here because we know that LoadIconA
360
-- -- needs the stdcall convention, as do
361
-- -- all standard .dll routines in the WIN32 API.
362
-- -- To specify the cdecl convention, we would have used "+LoadIconA".
363
--
364
-- if LoadIcon = -1 then
365
-- puts(1, "LoadIconA could not be found!\n")
366
-- end if
367
--
368
--
369
-- See Also:
370
-- ##demo\callmach.ex##, [[:c_func]], [[:define_c_proc]], [[:c_proc]], [[:open_dll]]
371
372937
373
sequence arg_types, atom return_type)
374937
if atom(routine_name) and not safe_address(routine_name, 1, A_EXECUTE) then
3751
crash("A C function is being defined from Non-executable memory.")
376
end if
377936
return machine_func(M_DEFINE_C, {lib, routine_name, arg_types, return_type})
378
end function
379
380
--****
381
-- Signature:
382
-- function c_func(integer rid, sequence args={})
383
--
384
-- Description:
385
-- Call a C function, or machine code function, or translated/compiled Euphoria function by routine id.
386
--
387
-- Parameters:
388
-- # ##rid## : an integer, the routine_id of the external function being called.
389
-- # ##args## : a sequence, the list of parameters to pass to the function
390
--
391
-- Returns:
392
-- An **object**, whose type and meaning was defined on calling [[:define_c_func]]().
393
--
394
-- Errors:
395
-- If ##rid## is not a valid routine id, or the arguments do not match the prototype of
396
-- the routine being called, an error occurs.
397
--
398
-- Comments:
399
-- ##rid## must have been returned by [[:define_c_func]](), **not** by [[:routine_id]](). The
400
-- type checks are different, and you would get a machine level exception in the best case.
401
--
402
-- If the function does not take any arguments then ##args## should be ##{}##.
403
--
404
-- If you pass an argument value which contains a fractional part, where the C function expects
405
-- 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.
406
--
407
-- The function could be part of a .dll or .so created by the Euphoria To C Translator. In this case,
408
-- a Euphoria atom or sequence could be returned. C and machine code functions can only return
409
-- integers, or more generally, atoms (IEEE floating-point numbers).
410
--
411
-- Example 1:
412
--
413
-- atom user32, hwnd, ps, hdc
414
-- integer BeginPaint
415
--
416
-- -- open user32.dll - it contains the BeginPaint C function
417
-- user32 = open_dll("user32.dll")
418
--
419
-- -- the C function BeginPaint takes a C int argument and
420
-- -- a C pointer, and returns a C int as a result:
421
-- BeginPaint = define_c_func(user32, "BeginPaint",
422
-- {C_INT, C_POINTER}, C_INT)
423
--
424
-- -- call BeginPaint, passing hwnd and ps as the arguments,
425
-- -- hdc is assigned the result:
426
-- hdc = c_func(BeginPaint, {hwnd, ps})
427
--
428
--
429
-- See Also:
430
--
431
-- [[:c_proc]], [[:define_c_proc]], [[:open_dll]], [[:Platform-Specific Issues]]
432
--
433
434
--****
435
-- Signature:
436
-- procedure c_proc(integer rid, sequence args={})
437
--
438
-- Description:
439
-- Call a C void function, or machine code function, or translated/compiled Euphoria procedure by routine id.
440
--
441
-- Parameters:
442
-- # ##rid## : an integer, the routine_id of the external function being called.
443
-- # ##args## : a sequence, the list of parameters to pass to the function
444
--
445
-- Errors:
446
-- If ##rid## is not a valid routine id, or the arguments do not match the prototype of
447
-- the routine being called, an error occurs.
448
--
449
-- Comments:
450
-- ##rid## must have been returned by [[:define_c_proc]](), **not** by [[:routine_id]](). The
451
-- type checks are different, and you would get a machine level exception in the best case.
452
--
453
-- If the procedure does not take any arguments then ##args## should be ##{}##.
454
--
455
-- If you pass an argument value which contains a fractional part, where the C void function expects
456
-- 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.
457
--
458
-- Example 1:
459
--
460
-- atom user32, hwnd, rect
461
-- integer GetClientRect
462
--
463
-- -- open user32.dll - it contains the GetClientRect C function
464
-- user32 = open_dll("user32.dll")
465
--
466
-- -- GetClientRect is a VOID C function that takes a C int
467
-- -- and a C pointer as its arguments:
468
-- GetClientRect = define_c_proc(user32, "GetClientRect",
469
-- {C_INT, C_POINTER})
470
--
471
-- -- pass hwnd and rect as the arguments
472
-- c_proc(GetClientRect, {hwnd, rect})
473
--
474
--
475
-- See Also:
476
-- [[:c_func]], [[:define_c_func]], [[:open_dll]], [[:Platform-Specific Issues]]
477
--
478
479101
constant M_CALL_BACK = 52
480
481
--**
482
-- Get a machine address for an Euphoria procedure.
483
--
484
-- Parameters:
485
-- # ##id## : an object, either the id returned by [[:routine_id]] for the function/procedure, or a pair {'+', id}.
486
--
487
-- Returns:
488
-- An **atom**, the address of the machine code of the routine. It can be
489
-- used by Windows, or an external C routine in a Windows .dll or Unix-like
490
-- shared library (.so), as a 32-bit "call-back" address for calling your
491
-- Euphoria routine.
492
--
493
-- Errors:
494
-- The length of ##name## should not exceed 1,024 characters.
495
--
496
-- Comments:
497
-- By default, your routine will work with the stdcall convention. On
498
-- Windows, you can specify its id as {'+', id}, in which case it will
499
-- work with the cdecl calling convention instead. On non-Microsoft
500
-- platforms, you should only use simple IDs, as there is just one standard
501
-- calling convention, i.e. cdecl.
502
--
503
-- You can set up as many call-back functions as you like, but they must all be Euphoria
504
-- functions (or types) with 0 to 9 arguments. If your routine has nothing to return
505
-- (it should really be a procedure), just return 0 (say), and the calling C routine can
506
-- ignore the result.
507
--
508
-- When your routine is called, the argument values will all be 32-bit unsigned (positive)
509
-- values. You should declare each parameter of your routine as atom, unless you want to
510
-- impose tighter checking. Your routine must return a 32-bit integer value.
511
--
512
-- You can also use a call-back address to specify a Euphoria routine as an exception
513
-- handler in the Linux/FreeBSD signal() function. For example, you might want to catch
514
-- the SIGTERM signal, and do a graceful shutdown. Some Web hosts send a SIGTERM to a CGI
515
-- process that has used too much CPU time.
516
--
517
-- A call-back routine that uses the cdecl convention and returns a floating-point result,
518
-- might not work with euiw. This is because the Watcom C compiler (used to build euiw) has
519
-- a non-standard way of handling cdecl floating-point return values.
520
--
521
-- Example 1:
522
-- See: ##demo\win32\window.exw##, ##demo\linux\qsort.ex##
523
--
524
-- See Also:
525
-- [[:routine_id]]
526
527185
528185
return machine_func(M_CALL_BACK, id)
529
end function