Some bits are just copied from https://github.com/DavideGalilei/nimtesseract (the memory management elements, that I still don't manage well). But I wanted to be able to use leptonica, because many tesseract functions require it to work.
I just wrapped the basic things to being able to work with TIFF and calculate the orientation.
There are many functions commented (not tested), but it should be easy to get those working if needed.
They might be useful for others.
I just have simply more experience with nimterop (the first one I used), and now I end up using most of the times c2nim. Given that sometimes both fails I end up using c2nim and nimterop in order to get inspiration about how to get thinks working.
I tried cinterop once, but I think it is only worth it when you are interested in using only a small portion from a library.
Regarding futhark, I have never tried it. I just tried the following:
import futhark
importc:
path "/usr/include/leptonica"
"allheaders.h"
{.passL:"-lleptopnica".}
var inputPix = pixRead("/home/jose/docs/scanned/salida.png".cstring)
var rotatedPix = pixRotate90(inputPix, 1.cint)
discard pixWrite("rotated_image.jpg".cstring, rotatedPix, IFF_JFIF_JPEG.cint)
But it fails with:
➜ src nim c leptonica.nim
Hint: used config file '/home/jose/.choosenim/toolchains/nim-2.0.2/config/nim.cfg' [Conf]
Hint: used config file '/home/jose/.choosenim/toolchains/nim-2.0.2/config/config.nims' [Conf]
..............................................................................................................................................
/home/jose/.nimble/pkgs2/futhark-0.12.2-cd781cfc8519fb2353979af90972e6749ab5a3ac/futhark.nim(716, 7) Hint: Running: opir -I/usr/include/leptonica -I/usr/lib/clang/16/include /home/jose/.cache/nim/leptonica_d/futhark-includes.h [User]
/home/jose/.nimble/pkgs2/futhark-0.12.2-cd781cfc8519fb2353979af90972e6749ab5a3ac/futhark.nim(734, 3) Hint: Parsing Opir output [User]
stack trace: (most recent call last)
/home/jose/.nimble/pkgs2/futhark-0.12.2-cd781cfc8519fb2353979af90972e6749ab5a3ac/futhark.nim(738, 13) importcImpl
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/json.nim(1040, 23) parseJson
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/json.nim(953, 4) parseJson
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/parsejson.nim(113, 15) open
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/lexbase.nim(150, 13) open
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/lexbase.nim(89, 32) fillBuffer
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/streams.nim(254, 31) readDataStr
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/pure/streams.nim(1219, 50) ssReadDataStr
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/system/indices.nim(86, 12) []
/home/jose/src/nimlang/leptonica_futhark/src/leptonica.nim(3, 1) template/generic instantiation of `importc` from here
/home/jose/.nimble/pkgs2/futhark-0.12.2-cd781cfc8519fb2353979af90972e6749ab5a3ac/futhark.nim(660, 14) template/generic instantiation of `importcImpl` from here
/home/jose/.choosenim/toolchains/nim-2.0.2/lib/system/indices.nim(86, 12) Error: interpretation requires too many iterations; if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: 10000000)
I don't know if I am using it correctly.
I think futhark would benefit from having links to some working examples. If you look at nimterop, they have this that can serve as inspiration.
I always have to add a zero or two when using futhark
I futhark is based on clang compiler. If it compiles with clang, it is very likely that futhark will generate low level bindings successfully
Thanks @giaco.
Now I get:
/home/jose/.nimble/pkgs2/futhark-0.12.2-cd781cfc8519fb2353979af90972e6749ab5a3ac/futhark.nim(212, 10) Error: Unknown kind in findAlias: {"kind":"invalid","value":"???"}
Ooh, that's a rare bug! Or rather some part of the C spec I haven't encountered yet. Probably an easy fix though.
And having links to examples is a great idea!
That's great. I tried it and worked really well. I like that it just works. I don't like much that the generated binding requires about 3 times more lines:
when not declared(pixwrite):
proc pixwrite*(fname: cstring; pix: ptr Pix_520094250; format: lint32_520094097): lok_520094087 {.
cdecl, importc: "pixWrite".}
else:
static :
hint("Declaration of " & "pixwrite" & " already exists, not redeclaring")
versus:
proc pixWrite*(fname: cstring; pix: ptr Pix; format: LInt32): LOk {.
importc: "pixWrite".}
I wonder if the when/else can be deactivated. Just to have the API in a more compact way. I don't like much the naming of the types, but I get that come fixed with sed.
I will try it in the future for sure.
Any plan to the same with C++ or is not possible?
Ah yes, those are part of the "it just works" philosophy of Futhark. Unlike c2nim and nimterop you're not supposed to edit neither the code going in, nor the code coming out. To facilitate this Futhark adds these guard statements. You can disable them with -d:nodeclguards at the risk of the wrapper maybe breaking. To rename things you can also register a renameCallback which is called for each identifier and allows you to apply any naming scheme you like without the hassle of post processing.
C++ support is also planned, just haven't gotten around to it yet.