cimport

Main import file to write wrappers. Each compileTime proc must be used in a compile time context, eg using:

static:
  cAddStdDir()

Procs

proc cSkipSymbol(skips: seq[string]) {...}{.compileTime, raises: [], tags: [].}
Similar to cOverride(), this macro allows filtering out symbols not of interest from the generated output.

Examples:

static :
  cSkipSymbol @["proc1", "Type2"]
proc cSearchPath(path: string): string {...}{.compileTime, raises: [], tags: [ReadDirEffect].}

Get full path to file or directory path in search path configured using cAddSearchDir() and cAddStdDir().

This can be used to locate files or directories that can be passed onto cCompile(), cIncludeDir() and cImport().

proc cDebug() {...}{.compileTime, raises: [], tags: [].}
Enable debug messages and display the generated Nim code
proc cDisableCaching() {...}{.compileTime, raises: [], tags: [].}

Disable caching of generated Nim code - useful during wrapper development

If files included by header being processed by cImport() change and affect the generated content, they will be ignored and the cached value will continue to be used . Use cDisableCaching() to avoid this scenario during development.

nim -f was broken prior to 0.19.4 but can also be used to flush the cached content.

proc cAddSearchDir(dir: string) {...}{.compileTime, raises: [], tags: [].}
Add directory dir to the search path used in calls to cSearchPath().

Examples:

import
  paths, os

static :
  cAddSearchDir testsIncludeDir()
doAssert cSearchPath("test.h").existsFile
proc cAddStdDir(mode = "c") {...}{.compileTime, raises: [], tags: [].}
Add the standard c [default] or cpp include paths to search path used in calls to cSearchPath()

Examples:

static :
  cAddStdDir()
import
  os

doAssert cSearchPath("math.h").existsFile

Macros

macro cOverride(body): untyped

When the wrapper code generated by nimterop is missing certain symbols or not accurate, it may be required to hand wrap them. Define them in a cOverride() macro block so that Nimterop no longer defines these symbols.

For example:

int svGetCallerInfo(const char** fileName, int *lineNumber);

This might map to:

proc svGetCallerInfo(fileName: ptr cstring; lineNumber: var cint)

Whereas it might mean:

cOverride:
  proc svGetCallerInfo(fileName: var cstring; lineNumber: var cint)

Using the cOverride() block, nimterop can be instructed to skip over svGetCallerInfo(). This works for procs, consts and types.

macro cPlugin(body): untyped
When cOverride() and cSkipSymbol() are not adequate, the cPlugin() macro can be used to customize the generated Nim output. The following callbacks are available at this time.
proc onSymbol(sym: var Symbol) {.exportc, dynlib.}

onSymbol() can be used to handle symbol name modifications required due to invalid characters like leading/trailing _ or rename symbols that would clash due to Nim's style insensitivity. It can also be used to remove prefixes and suffixes like SDL_. The symbol name and type is provided to the callback and the name can be modified.

Returning a blank name will result in the symbol being skipped. This will fail for nskParam and nskField since the generated Nim code will be wrong.

Symbol types can be any of the following:

  • nskConst for constants
  • nskType for type identifiers, including primitive
  • nskParam for param names
  • nskField for struct field names
  • nskEnumField for enum (field) names, though they are in the global namespace as nskConst
  • nskProc - for proc names

nimterop/plugins is implicitly imported to provide access to standard plugin facilities.

Examples:

cPlugin:
  import
    strutils

  proc onSymbol*(sym: var Symbol) {...}{.exportc, dynlib.} =
    sym.name = sym.name.strip(chars = {'_'})

Examples:

cPlugin:
  import
    strutils

  proc onSymbol*(sym: var Symbol) {...}{.exportc, dynlib.} =
    if sym.kind == nskProc and sym.name.contains("SDL_"):
      sym.name = sym.name.replace("SDL_", "")
macro cDefine(name: static string; val: static string = ""): untyped
#define an identifer that is forwarded to the C/C++ compiler using {.passC: "-DXXX".}
macro cIncludeDir(dir: static string): untyped
Add an include directory that is forwarded to the C/C++ compiler using {.passC: "-IXXX".}. This is also provided to the preprocessor during Nim code generation.
macro cCompile(path: static string; mode = "c"; exclude = ""): untyped

Compile and link C/C++ implementation into resulting binary using {.compile.}

path can be a specific file or contain wildcards:

cCompile("file.c")
cCompile("path/to/*.c")

mode recursively searches for code files in path.

c searches for *.c whereas cpp searches for *.C *.cpp *.c++ *.cc *.cxx

cCompile("path/to/dir", "cpp")

exclude can be used to exclude files by partial string match. Comma separated to specify multiple exclude strings

cCompile("path/to/dir", exclude="test2.c")
macro cImport(filename: static string; recurse: static bool = false): untyped

Import all supported definitions from specified header file. Generated content is cached in nimcache until filename changes unless cDisableCaching() is set. nim -f can also be used after Nim v0.19.4 to flush the cache.

recurse can be used to generate Nim wrappers from #include files referenced in filename. This is only done for files in the same directory as filename or in a directory added using cIncludeDir()