Expand/Shrink

define_c_func

Definition: integer rid = define_c_func(object lib, object fname, sequence args, atom return_type, bool bCrash=true)
Description: Define the characteristics of a C function that you wish to call from your Phix program. A small integer, known as a routine id, is returned, or -1 if the function cannot be found (and bCrash is false).
pwa/p2js: Not supported.
Comments: lib is either an (atom) address returned by open_dll(), or {}.
If lib is an atom, fname is the (string) name of a function within that dll, optionally as either {'+',"name"} or "+name" to specify the CDECL calling convention.
If lib is {}, fname is the (atom) address of a machine code function, optionally as {'+',addr} to specify the CDECL calling convention.

CDECL is the default/only calling convention on a Linux system.
STDCALL is the default in a Windows system.
The CDECL convention requires the callee to clean up the stack, and is therefore more suited to a variable number of arguments, whereas with STDCALL the routine cleans up the stack before returning, however it is entirely dependent on how the dll/so was built.

args is a list of the parameter types for the function, return_type should be self explanatory.

The define_cffi_func routine is a string-based wrapper of this routine, which you may find slightly easier to use.

The following C types are predefined (in psym.e/syminit):

                    C_BYTE = #01000001,     -- an 8 bit signed integer
                    C_CHAR = C_BYTE,
                   C_UCHAR = #02000001,     -- an 8 bit unsigned integer
                   C_UBYTE = C_UCHAR,
                   C_SHORT = #01000002,     -- a 16 bit signed integer
                    C_WORD = C_SHORT,
                  C_USHORT = #02000002,     -- a 16 bit unsigned integer
                     C_INT = #01000004,     -- a 32 bit signed integer
                    C_BOOL = C_INT,
                    C_UINT = #02000004,     -- a 32 bit unsigned integer
                   C_DWORD = C_UINT,
                   C_INT64 = #01000008,     -- a 64 bit signed integer
                   C_QWORD = #02000008,     -- a 64 bit unsigned integer
                    C_LONG = iff(machine_bits()=32 or platform()=WINDOWS ? C_INT  : C_INT64),
                   C_ULONG = iff(machine_bits()=32 or platform()=WINDOWS ? C_UINT : C_QWORD),
                     C_PTR = iff(machine_bits()=32                       ? C_UINT : C_QWORD),
                 C_POINTER = C_PTR,
                  C_HANDLE = C_PTR,
                    C_HWND = C_PTR,
                   C_FLOAT = #03000004,     -- a 32-bit float
                  C_DOUBLE = #03000008      -- a 64-bit float


The resulting routine id, rid, can be passed to c_func() when you want to call the C function.

You can pass or return any C integer type or pointer type. You can also pass a Phix atom as a C double or float, and get a C double or float returned to you as a Phix atom.

In C (on Windows and Linux), parameter types which use 4 bytes or less are all passed the same way, so it is not necessary to be exact. 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.

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().

The C type "long double" should be avoided at all costs - it is highly compiler-dependent and can be 10/8/12/16 bytes aligned to an 8/2/4/16 byte boundary.
Auxillary function: integer res = sizeof(integer c_type) - returns the size in bytes of the above types.
Example:
-- user32.dll contains the LoadIconA C function which takes a C pointer and a C int as parameters
-- and returns a C int as a result.
atom user32 = open_dll("user32.dll")
integer xLoadIcon = define_c_func(user32, "LoadIconA", {C_PTR, C_INT}, C_INT)
The naming convention of xLoadIcon is partly a personal preference but it can also improve the help system in Edita/Edix, when F1 is keyed, as they both strip a leading "x" when looking for a chm file to open.
Implementation: See builtins\VM\pcfunc.e (an autoinclude) for details of the actual implementation.
The ancilliary function sizeof() is however implemented in the autoinclude builtins\dll.e
See Also: c_func, define_cffi_func, define_c_proc, c_proc, open_dll, Calling C Functions, platform, machine_bits
Expand/Shrink