Hello - I'm trying to use Futhark to create bindings for various things. I'm starting with CozoDB as I'm interested in it and the API is tiny. https://github.com/cozodb/cozo/blob/main/cozo-lib-c/example.c
I've been struggling to link the provided DLLs in the compiler.
With the below code it seems to try and link statically when using the lib files,but this way is taking a very long time . Maybe this is because the library itself is a hefty 250mb, I assume because it brings with it mysql and rocksdb backend by default.
import futhark
import strutils
# Tell futhark where to find the C libraries you will compile with, and what
# header files you wish to import.
importc:
  path "./lib/c"
  "cozo_c.h"
{.passL: "-Llib/static -llibcozo_c".}
proc query(db_id: int32, query: cstring) =
    let empty_params = "{}"
    var res: cstring
    res = cozo_run_query(db_id, query, empty_params, false)
    echo $res
    cozo_free_str(res)
proc main() =
    var db_id: int32
    var err: cstring
    err = cozo_open_db("mem", "", "{}", addr db_id)
    
    if err != nil :
        echo $err
        cozo_free_str(err)
        return
    
    query(db_id, "?[] <- [[1, 2, 3]]")
    
    echo cozo_close_db(db_id)
main()
So I have two questions:
- How can I adapt this to use DLLs? And how do I link/bind to DLLs in general?
 - Will using DLLs in this specific case prevent the very slow compile step that seems to occur?
 
Thanks :)
You're very close, the only thing missing is a tiny bit of C linking experience. I dropped the .h file and the .so (Linux's version of a .dll) in the same folder as this Nim file:
import futhark
import strutils
# Tell futhark where to find the C libraries you will compile with, and what
# header files you wish to import.
importc:
  path "."
  "cozo_c.h"
{.passL: "-L. -lcozo_c".}
proc query(db_id: int32, query: cstring) =
  let empty_params = "{}"
  var res: cstring
  res = cozo_run_query(db_id, query, empty_params, false)
  echo $res
  cozo_free_str(res)
proc main() =
  var db_id: int32
  var err: cstring
  err = cozo_open_db("mem", "", "{}", addr db_id)
  
  if err != nil :
    echo $err
    cozo_free_str(err)
    return
  
  query(db_id, "?[] <- [[1, 2, 3]]")
  
  echo cozo_close_db(db_id)
main()
Then it's a simple nim c <ourfile>.nim to build the binary. Now this is dynamically linked to libcozo_c.so, but running it will throw an error (on Linux, on Windows you're fine since the library is in the same folder). We need to tell it to look for the dynamic library in the local folder and not just in the system folders: LD_LIBRARY_PATH=. ./<ourfile>. And there you go, a dynamically linked library which runs fine.
Of course you could clean it up a little bit while we're at it:
import futhark
import strutils
# Tell futhark where to find the C libraries you will compile with, and what
# header files you wish to import.
proc renameCallback(name, kind: string, partOf = ""): string =
  result = name
  result.removePrefix("cozo_")
importc:
  renameCallback renameCallback
  path "."
  "cozo_c.h"
{.passL: "-L. -lcozo_c".}
proc query(dbId: cint, query: cstring) =
  let
    emptyParams = "{}"
    res = dbId.runQuery(query, emptyParams, false)
  echo $res
  freeStr(res)
var
  dbId: cint
  err = openDb("mem", "", "{}", addr dbId)
if err != nil:
  echo $err
  freeStr(err)
  quit 1
dbId.query("?[] <- [[1, 2, 3]]")
echo dbId.closeDb