diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2019-01-24 22:44:16 -0600 |
|---|---|---|
| committer | genotrance <dev@genotrance.com> | 2019-01-27 22:05:54 -0600 |
| commit | d8c75a43f725ca3fc4111a55587ce5ca69d024e9 (patch) | |
| tree | 8e770cfd35219b37517c4731056a1e34d9640fc6 | |
| parent | f367234ca5da349a00982e6a7d70fdcd80404141 (diff) | |
| download | nimterop-d8c75a43f725ca3fc4111a55587ce5ca69d024e9.tar.gz nimterop-d8c75a43f725ca3fc4111a55587ce5ca69d024e9.zip | |
Plugin support
| -rw-r--r-- | .travis.yml | 2 | ||||
| -rw-r--r-- | appveyor.yml | 1 | ||||
| -rw-r--r-- | nimterop/cimport.nim | 15 | ||||
| -rw-r--r-- | nimterop/getters.nim | 36 | ||||
| -rw-r--r-- | nimterop/globals.nim | 6 | ||||
| -rw-r--r-- | nimterop/grammar.nim | 16 | ||||
| -rw-r--r-- | tests/tnimterop_c.nim | 7 | ||||
| -rw-r--r-- | toast.nim | 8 |
8 files changed, 72 insertions, 19 deletions
diff --git a/.travis.yml b/.travis.yml index 8632daf..3118652 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,11 @@ os: language: c env: - - BRANCH=0.19.0 - BRANCH=0.19.2 - BRANCH=devel cache: directories: - - "$HOME/.choosenim/toolchains/nim-0.19.0" - "$HOME/.choosenim/toolchains/nim-0.19.2" install: diff --git a/appveyor.yml b/appveyor.yml index 5768382..f8f45d7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,6 @@ matrix: environment: matrix: - - NIM_VERSION: 0.19.0 - NIM_VERSION: 0.19.2 for: diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim index ce0ae18..8fcf66e 100644 --- a/nimterop/cimport.nim +++ b/nimterop/cimport.nim @@ -1,4 +1,4 @@ -import macros, os, strformat, strutils +import hashes, macros, os, ospaths, strformat, strutils const CIMPORT {.used.} = 1 @@ -102,6 +102,9 @@ proc getToast(fullpath: string, recurse: bool = false): string = if gStateCT.symOverride.len != 0: cmd.add &"--symOverride={gStateCT.symOverride.join(\",\")} " + if gStateCT.pluginFile.nBl and gStateCT.pluginFile.fileExists(): + cmd.add &"--pluginFile={gStateCT.pluginFile.quoteShell} " + cmd.add &"{fullpath.quoteShell}" echo cmd (result, ret) = gorgeEx(cmd, cache=getCacheValue(fullpath)) @@ -170,6 +173,16 @@ macro cSkipSymbol*(skips: varargs[string]): untyped = for skip in skips: gStateCT.symOverride.add skip.strVal +macro cPlugin*(body): untyped = + let + data = body.repr + path = getTempDir() / "nimterop" & ($data.hash() & ".nim") + + if not fileExists(path): + writeFile(path, data) + + gStateCT.pluginFile = path + proc cSearchPath*(path: string): string {.compileTime.}= ## Get full path to file or directory ``path`` in search path configured ## using `cAddSearchDir() <cimport.html#cAddSearchDir.m,>`_ and diff --git a/nimterop/getters.nim b/nimterop/getters.nim index 24e250d..ed0652d 100644 --- a/nimterop/getters.nim +++ b/nimterop/getters.nim @@ -1,4 +1,4 @@ -import macros, os, sequtils, sets, strformat, strutils, tables +import dynlib, macros, os, sequtils, sets, strformat, strutils, tables import regex @@ -88,7 +88,14 @@ proc getType*(str: string): string = result = gTypeMap[result] proc getIdentifier*(str: string): string = - result = str.strip(chars={'_'}).replace(re"_+", "_") + doAssert str.len != 0, "Blank identifier error" + + if gStateRT.onSymbol != nil: + result = gStateRT.onSymbol(str) + else: + result = str + + doAssert result[0] != '_' and result[^1] != '_', &"Identifier '{result}' with leading/trailing underscore '_' not supported: use cPlugin() to handle" if result in gReserved: result = &"`{result}`" @@ -306,4 +313,27 @@ proc getNimExpression*(expr: string): string = proc getSplitComma*(joined: seq[string]): seq[string] = for i in joined: - result = result.concat(i.split(","))
\ No newline at end of file + result = result.concat(i.split(",")) + +proc dll*(path: string): string = + let + (dir, name, ext) = path.splitFile() + + when defined(Windows): + result = dir/name.addFileExt("dll") + when defined(Linux): + result = dir/"lib" & name.addFileExt("so") + when defined(OSX): + result = dir/"lib" & name.addFileExt("dynlib") + +proc loadPlugin*(fullpath: string) = + doAssert fileExists(fullpath), "Plugin file does not exist: " & fullpath + if not fileExists(fullpath.dll): + discard execAction("nim c --app:lib " & fullpath) + doAssert fileExists(fullpath.dll), "No plugin binary generated for " & fullpath + + let lib = loadLib(fullpath.dll) + doAssert lib != nil, "Plugin load failed" + + gStateRT.onSymbol = cast[proc(sym: string): string {.cdecl.}](lib.symAddr("onSymbol")) + doAssert gStateRT.onSymbol != nil, "onSymbol() load failed" diff --git a/nimterop/globals.nim b/nimterop/globals.nim index 42abf8f..e24e51d 100644 --- a/nimterop/globals.nim +++ b/nimterop/globals.nim @@ -51,15 +51,15 @@ type nocache*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool consts*, enums*, procs*, types*: HashSet[string] - - code*, constStr*, currentHeader*, debugStr*, enumStr*, mode*, procStr*, typeStr*: string - sourceFile*: string # eg, C or C++ source or header file + constStr*, debugStr*, enumStr*, procStr*, typeStr*: string + code*, currentHeader*, mode*, pluginFile*, sourceFile*: string ast*: Table[string, seq[ref Ast]] data*: seq[tuple[name, val: string]] when not declared(CIMPORT): grammar*: seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode) {.nimcall.}]] + onSymbol*: proc(sym: string): string {.cdecl.} var gStateCT {.compiletime, used.}: State gStateRT {.used.}: State diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim index f86db19..5a7ca66 100644 --- a/nimterop/grammar.nim +++ b/nimterop/grammar.nim @@ -344,11 +344,11 @@ proc initGrammar() = )) proc pEnumCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) = - var - nname = name.getIdentifier() - - if nname.len == 0: - nname = getUniqueIdentifier(gStateRT.enums, "Enum") + let nname = + if name.len == 0: + getUniqueIdentifier(gStateRT.enums, "Enum") + else: + name.getIdentifier() if gStateRT.enums.addNewIdentifer(nname): gStateRT.enumStr &= &"\ntype {nname}* = distinct int" @@ -358,13 +358,13 @@ proc initGrammar() = i = fstart count = 0 while i < gStateRT.data.len-fend: - let - fname = gStateRT.data[i].val.getIdentifier() - if gStateRT.data[i].name == "enumerator": i += 1 continue + let + fname = gStateRT.data[i].val.getIdentifier() + if i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name in gEnumVals: if gStateRT.consts.addNewIdentifer(fname): diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim index f0d5ed5..095fe20 100644 --- a/tests/tnimterop_c.nim +++ b/tests/tnimterop_c.nim @@ -8,6 +8,13 @@ cDefine("FORCE") cIncludeDir "$projpath/include" cAddSearchDir "$projpath/include" cCompile cSearchPath("test.c") + +cPlugin: + import strutils + + proc onSymbol*(sym: string): string {.exportc, dynlib.} = + return sym.strip(chars={'_'}) + cImport cSearchPath "test.h" check TEST_INT == 512 @@ -113,6 +113,7 @@ proc main( defines: seq[string] = @[], includeDirs: seq[string] = @[], symOverride: seq[string] = @[], + pluginFile: string = "", source: seq[string], ) = @@ -126,11 +127,15 @@ proc main( debug: debug, defines: defines, includeDirs: includeDirs, - symOverride: symOverride + symOverride: symOverride, + pluginFile: pluginFile ) gStateRT.symOverride = gStateRT.symOverride.getSplitComma() + if pluginFile.nBl: + loadPlugin(pluginFile) + if pgrammar: parseGrammar() printGrammar() @@ -146,6 +151,7 @@ when isMainModule: "defines": "definitions to pass to preprocessor", "includeDirs": "include directory to pass to preprocessor", "symOverride": "skip generating specified symbols", + "pluginFile": "Nim file to build and load as a plugin", "preprocess": "run preprocessor on header", "pgrammar": "print grammar", "recurse": "process #include files", |
