The answer to this question is probably very simple, but I can't seem to get it to work, and the documnetation is very sparse for these functions for some reason. I need to read a linux device file until there is nothing left to read for 0.1 second. I know that I need to use a selector, but I can't for the life of me work out how to get the file descriptor from the file object created with the open command.
So how do I get a file descriptor for use with selector.registerHandle() from a file object created with open()?
There is also proc open*(a1: cstring, a2: cint) in the posix module:
import posix
let fd = open("/dev/mydevice", O_RDONLY)
if you want an unbuffered raw file handle which sounds like it might be the case (and you don't need portability which is implied by your Linux device file use-case context).Thank you very much. You are quite correct. An unbuffered file is ideal, and yes, linux only (OpenWrt). Thank you for pointing me to the posix module (and getFileHandle()). I am trying to decipher the most elegant way of accomplishing this, but am failing miserably. this is what I have (UsbDevice.devicePaths[0] is a string containing the path of the device file):
proc readDevice(dev: UsbDevice): DeviceReading =
let devfd = posix.open(dev.devicePaths[0], posix.O_RDWR)
# Close the file object when we are done with it
defer: discard posix.close(devfd)
#write trigger data to the device file
let writepack = [0x01'u8, 0x86'u8, 0xff'u8, 0x01'u8, 0'u8, 0'u8, 0'u8, 0'u8]
let written = posix.write(devfd, cast [ptr uint8](unsafeAddr(writepack)), writepack.len)
#now read until there is no more data for 100ms
while true:
var selector = newSelector[int]() # I don't need user data, so is int correct for T?
selector.registerHandle(cast[int](devfd), {Read}, 0)
var ready = selector.select(100)
echo(ready) # this is just to check that my selector is working.
break
#more code to come after the selector is working...........
But it won't compile:
$ sudo nim c -r temper.nim
Hint: used config file '/etc/nim/nim.cfg' [Conf]
Hint: system [Processing]
Hint: temper [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: bitops [Processing]
Hint: algorithm [Processing]
Hint: unicode [Processing]
Hint: sets [Processing]
Hint: hashes [Processing]
Hint: os [Processing]
Hint: times [Processing]
Hint: options [Processing]
Hint: typetraits [Processing]
Hint: strformat [Processing]
Hint: macros [Processing]
Hint: posix [Processing]
Hint: ospaths [Processing]
Hint: re [Processing]
Hint: pcre [Processing]
Hint: rtarrays [Processing]
Hint: tables [Processing]
Hint: selectors [Processing]
Hint: nativesockets [Processing]
Hint: epoll [Processing]
Hint: sequtils [Processing]
temper.nim(105, 25) template/generic instantiation from here
../../../../usr/lib/nim/pure/ioselects/ioselectors_epoll.nim(475, 25) template/generic instantiation from here
../../../../usr/lib/nim/pure/ioselects/ioselectors_epoll.nim(390, 35) Error: undeclared field: 'SockLen'
Well, to make it work without the rest of your type environment, I changed just the first couple lines of your posted code to:
import posix, selectors
proc readDevice(dev: string) =
let devfd = posix.open(dev, posix.O_RDWR)
Then it compiled fine for me. I usually run a pretty fresh devel version of Nim. You may be on some earlier Nim. It's probably more useful long-term for you to learn to install a devel version of Nim than for me to test on back-dated versions.Agreed, I don't want to waste your time, and am happy to update. I am using
Nim Compiler Version 0.19.0 [Linux: amd64]
Compiled at 2018-10-27
Copyright (c) 2006-2018 by Andreas Rumpf
active boot switches: -d:release
Which was installed from the default Ubuntu 18.10 repository. Is there a better version to install?
Thanks again.
Cheers for your help. You are right, compiling Nim is not that hard. Just for anyone who finds this thread:
sudo apt install nim
git clone https://github.com/Araq/Nim
cd Nim
sh build_all.sh
and I have nim 0.19.9 (compiled, but not installed). Whilst this is great, reading from a device file is kind of a basic requirement for my application that shouldn't take days to work out, or a bleeding edge release to get it to work. I was hoping to not have to code a complex application in C, or put up with the eccentricities of Lua to accomplish my goals.
I have just today received my "Nim in action" book so hopefully I'll revisit this later but for now I'll have to put up with "do return end" and other such stupidities associated with a minimalist interpreter. Many thanks for all your help, and I'll definitely be back when the language is ready.
So after reading "Nim in Action" I decided to have another go and managed to get everything to work. For anyone looking for an example of using selectors on a raw posix file, please take a look at my github respository for driving TEMPer USB thermometers from Nim (on linux). https://github.com/mp035/temper.nim
Thanks again for your help cblake.
You're welcome, and I'm very glad you didn't give up so quickly!
FWIW, I was not sure it was a problem with that version of Nim -- only that when I changed the type environment enough to compile your code that it worked for me on a devel version. In the future, providing more whole code context (even if only a link to a github repo) may help you get more precise guidance.
Having confidence getting a fresh devel build going will pay off someday, though, esp. if your OS package manager has one as old as 0.19.0. Even just more people submitting pull requests for stdlib documentation/API tweaks can help, and PRs usually make more sense to do against devel HEAD.