Skip to content

Instantly share code, notes, and snippets.

@jonas
Last active April 17, 2017 20:36
Show Gist options
  • Save jonas/fa7ada249afe5a7c9ebd67b44bf032e3 to your computer and use it in GitHub Desktop.
Save jonas/fa7ada249afe5a7c9ebd67b44bf032e3 to your computer and use it in GitHub Desktop.
Scala Native bindgen WIP
> sandbox/run
[warn] Credentials file /Users/fonseca/.bintray/.credentials does not exist
[info] Compiling 1 Scala source to /opt/scala-native/sandbox/target/scala-2.11/classes...
[info] Linking (886 ms)
[info] Discovered 767 classes and 4541 methods
[info] Optimizing (1293 ms)
[info] Generating intermediate code (244 ms)
[info] Produced 34 files
[info] Compiling to native code (1115 ms)
[info] Linking native code (216 ms)
@extern
object X {
def ___runetype(: __darwin_ct_rune_t): unsigned long = extern
def ___tolower(: __darwin_ct_rune_t): __darwin_ct_rune_t = extern
def ___toupper(: __darwin_ct_rune_t): __darwin_ct_rune_t = extern
def isascii(_c: CInt): CInt = extern
def __maskrune(: __darwin_ct_rune_t, : unsigned long): CInt = extern
def __istype(_c: __darwin_ct_rune_t, _f: unsigned long): CInt = extern
def __isctype(_c: __darwin_ct_rune_t, _f: unsigned long): __darwin_ct_rune_t = extern
def __toupper(: __darwin_ct_rune_t): __darwin_ct_rune_t = extern
def __tolower(: __darwin_ct_rune_t): __darwin_ct_rune_t = extern
def __wcwidth(_c: __darwin_ct_rune_t): CInt = extern
def isalnum(_c: CInt): CInt = extern
def isalpha(_c: CInt): CInt = extern
def isblank(_c: CInt): CInt = extern
def iscntrl(_c: CInt): CInt = extern
def isdigit(_c: CInt): CInt = extern
def isgraph(_c: CInt): CInt = extern
def islower(_c: CInt): CInt = extern
def isprint(_c: CInt): CInt = extern
def ispunct(_c: CInt): CInt = extern
def isspace(_c: CInt): CInt = extern
def isupper(_c: CInt): CInt = extern
def isxdigit(_c: CInt): CInt = extern
def toascii(_c: CInt): CInt = extern
def tolower(_c: CInt): CInt = extern
def toupper(_c: CInt): CInt = extern
def digittoint(_c: CInt): CInt = extern
def ishexnumber(_c: CInt): CInt = extern
def isideogram(_c: CInt): CInt = extern
def isnumber(_c: CInt): CInt = extern
def isphonogram(_c: CInt): CInt = extern
def isrune(_c: CInt): CInt = extern
def isspecial(_c: CInt): CInt = extern
}
import scalanative.native._, stdlib._, stdio._, string._
import scalanative.runtime.bindgen._
object Test {
import Bindgen._
sealed trait Node
case class Function(name: String, returnType: String, args: List[Function.Arg]) extends Node
object Function {
case class Arg(name: String, tpe: String)
}
val buffer = scala.collection.mutable.ListBuffer[Node]()
def showArg(i: Int, parent: CXCursor) = {
val cursor = Cursor_getArgument(parent, i)
val tpe = getCursorType(cursor)
val name = getCursorSpelling(cursor)
val typeSpelling = getTypeSpelling(tpe)
Function.Arg(fromCString(name), fromCString(typeSpelling))
}
def showArgs(cursor: CXCursor) = {
val argc = Cursor_getNumArguments(cursor)
var i = 0
var args = List.empty[Function.Arg]
while (i < argc) {
args = args :+ showArg(i, cursor)
i += 1
}
args
}
val visitor: Visitor = (cursor: CXCursor, parent: CXCursor, data: Data) => {
val kind: CXCursorKind = getCursorKind(cursor)
if (kind == CXCursor_FunctionDecl) {
val name = getCursorSpelling(cursor)
val cursorType = getCursorType(cursor)
val returnType = getResultType(cursorType)
val returnTypeSpelling = getTypeSpelling(returnType)
val argc = Cursor_getNumArguments(cursor)
buffer += Function(fromCString(name), fromCString(returnTypeSpelling), showArgs(cursor))
} else {
val name = getCursorSpelling(cursor)
val kindSpelling = getCursorKindSpelling(kind)
printf(c"Unhandled cursor kind for %s: %s\n", name, kindSpelling)
}
CXChildVisit_Recurse
}
def cToScala(tpe: String) = {
tpe match {
case "const char *" | "char *" => "CString"
case "int" => "CInt"
case unknown => unknown
}
}
def main(args: Array[String]): Unit = {
// val path = c"/opt/scala-native/sandbox/test.h"
val path = c"/usr/include/ctype.h"
val index = createIndex(0, 0)
val unit = parseTranslationUnit(index, path, null, 0, null, 0, CXTranslationUnit_SkipFunctionBodies)
val cursor = getTranslationUnitCursor(unit)
visitChildren(cursor, visitor, null)
disposeTranslationUnit(unit)
disposeIndex(index)
println("@extern")
println("object X {")
buffer.foreach {
case Function(name, returnType, args) =>
val argList = args.map(arg => s"${arg.name}: ${cToScala(arg.tpe)}").mkString(", ")
println(s" def $name($argList): ${cToScala(returnType)} = extern")
}
println("}")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment