Name | Executed | Routines | % | Executed | Lines | % | Unexecuted |
/home/matt/eu/rds/include/std/dll.e | 5 | 5 | 100.00% | 51 | 53 | 96.23% | 2 |
Routine | Executed | Lines | Unexecuted | |
define_c_proc() | 3 | 4 | 75.00% | 1 |
open_dll() | 8 | 9 | 88.89% | 1 |
call_back() | 2 | 2 | 100.00% | 0 |
define_c_func() | 4 | 4 | 100.00% | 0 |
define_c_var() | 2 | 2 | 100.00% | 0 |
# | 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 | |
28 | 101 | C_CHAR = #01000001, |
29 | --** byte 8-bits | |
30 | 101 | C_BYTE = #01000001, |
31 | --** unsigned char 8-bits | |
32 | 101 | C_UCHAR = #02000001, |
33 | --** ubyte 8-bits | |
34 | 101 | C_UBYTE = #02000001, |
35 | --** short 16-bits | |
36 | 101 | C_SHORT = #01000002, |
37 | --** word 16-bits | |
38 | 101 | C_WORD = #01000002, |
39 | --** unsigned short 16-bits | |
40 | 101 | C_USHORT = #02000002, |
41 | --** int 32-bits | |
42 | 101 | C_INT = #01000004, |
43 | --** bool 32-bits | |
44 | 101 | C_BOOL = C_INT, |
45 | --** unsigned int 32-bits | |
46 | 101 | C_UINT = #02000004, |
47 | --** size_t 32-bits | |
48 | 101 | C_SIZE_T = C_UINT, |
49 | --** long 32-bits | |
50 | 101 | C_LONG = C_INT, |
51 | --** unsigned long 32-bits | |
52 | 101 | C_ULONG = C_UINT, |
53 | --** any valid pointer 32-bits | |
54 | 101 | C_POINTER = C_UINT, |
55 | --** handle 32-bits | |
56 | 101 | C_HANDLE = C_UINT, |
57 | --** hwnd 32-bits | |
58 | 101 | C_HWND = C_UINT, |
59 | --** dword 32-bits | |
60 | 101 | C_DWORD = C_UINT, |
61 | --** wparam 32-bits | |
62 | 101 | C_WPARAM = C_LONG, |
63 | --** lparam 32-bits | |
64 | 101 | C_LPARAM = C_LONG, |
65 | --** hresult 32-bits | |
66 | 101 | C_HRESULT = C_LONG, |
67 | --** float 32-bits | |
68 | 101 | C_FLOAT = #03000004, |
69 | --** double 64-bits | |
70 | 101 | C_DOUBLE = #03000008, |
71 | --** dwordlong 64-bits | |
72 | 101 | 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 | |
82 | 101 | E_INTEGER = #06000004, |
83 | --** atom | |
84 | 101 | E_ATOM = #07000004, |
85 | --** sequence | |
86 | 101 | E_SEQUENCE= #08000004, |
87 | --** object | |
88 | 101 | E_OBJECT = #09000004 |
89 | ||
90 | ||
91 | --**** | |
92 | -- === Constants | |
93 | ||
94 | --** | |
95 | -- C's NULL pointer | |
96 | ||
97 | 101 | public constant NULL = 0 |
98 | ||
99 | 101 | constant M_OPEN_DLL = 50, |
100 | 101 | M_DEFINE_C = 51, |
101 | 101 | 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 | ||
161 | 307 | |
162 | 307 | if length(file_name) > 0 and string(file_name) then |
163 | 0 | 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 | |
168 | 307 | for idx = 1 to length(file_name) do |
169 | 15 | atom fh = machine_func(M_OPEN_DLL, file_name[idx]) |
170 | 15 | if not fh = 0 then |
171 | 3 | return fh |
172 | end if | |
173 | 12 | end for |
174 | ||
175 | 304 | 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 | ||
199 | 2 | |
200 | 2 | 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 | ||
275 | 1 | |
276 | sequence arg_types) | |
277 | 1 | if atom(routine_name) and not safe_address(routine_name, 1, A_EXECUTE) then |
278 | 0 | crash("A C function is being defined from Non-executable memory.") |
279 | end if | |
280 | 1 | 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 | ||
372 | 937 | |
373 | sequence arg_types, atom return_type) | |
374 | 937 | if atom(routine_name) and not safe_address(routine_name, 1, A_EXECUTE) then |
375 | 1 | crash("A C function is being defined from Non-executable memory.") |
376 | end if | |
377 | 936 | return machine_func(M_DEFINE_C, {lib, routine_name, arg_types, return_type}) |
378 | end function | |
379 | ||
380 | --**** | |
381 | -- Signature: | |
382 | -- | |
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 | -- | |
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 | ||
479 | 101 | 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 | ||
527 | 185 | |
528 | 185 | return machine_func(M_CALL_BACK, id) |
529 | end function |