Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Calling C

Most of the code a program could use is written in C: the operating system, the C runtime, compression, databases, graphics. tiko calls C directly, with no wrapper between: a C function is declared, and then called like any other.

'' The C runtime is always linked, so its functions need only a
'' declaration.

'' One at a time: cdecl is C's calling convention, and alias gives the
'' exact name the linker looks for, so the tiko name can differ.
declare function CLength cdecl alias "strlen" _
    ( byval s as const zstring ptr ) as uinteger

'' A block: everything inside is cdecl and keeps its exact spelling.
extern "C"
    declare function toupper( byval c as int32 ) as int32
    declare function CAbs alias "abs" ( byval n as int32 ) as int32
    declare function atoi( byval s as const zstring ptr ) as int32
end extern

dim as zstring * 16 word = "interface"
print "strlen: "; CLength( @word )

for i as int32 = 0 to len( word ) - 1
    word[ i ] = toupper( word[ i ] )
next
print "toupper: "; word

print "abs:"; CAbs( -42 )
print "atoi:"; atoi( "  123 apples" )

Output

strlen: 9
toupper: INTERFACE
abs: 42
atoi: 123

A C function is declared with declare, plus what C needs:

  • cdecl: C's calling convention.
  • alias "name": the exact name the linker looks for. tiko names are not case-sensitive and C's are, so alias fixes the spelling; it also lets the tiko name differ, as CLength is C's strlen.
  • lib "name", optionally: the library the function lives in, which is then linked. The C runtime is always linked, so the example names none.

extern "C" ... end extern declares a block at once. Everything inside is cdecl and keeps the exact spelling it was written with, so toupper needs no alias. Inside the block alias still renames: CAbs is C's abs, which needs another name because abs is already a tiko function.

Pitfall

A declaration is a promise the compiler cannot check. It believes every parameter type and the result type. Copy them from the C header with care, or let the compiler read the header itself with #cinclude.

The pages that follow cover C types, C strings, callbacks, structs, reading a C header and loading a library at run time.

A larger C library is easiest to use as a vendor package: its header already translated and its compiled code beside it, reached with one #import. The toolchain ships SQLite this way; see SQLite.

Activities

  1. Declare C's tolower in the extern "C" block and lower-case the word again.
  2. Declare atoi with declare ... cdecl alias instead of in the block.