I'd like for this program to be able to do two things: check for console input asynchronously and load a dynamically linked library (some time after the console input checking begun). So here's what I tried:
import threadpool, dynlib
var
input: FlowVar[TaintedString]
command: string
proc asyncConsoleInput =
if input == nil:
input = spawn readLine(stdin)
elif input.isReady:
command = ^input
input = spawn readLine(stdin)
var
running = true
lib: LibHandle
while running:
# Console input
asyncConsoleInput()
if command != nil:
if command == "quit": running = false
command = nil
# Loading a DLL
if lib == nil:
echo "loading lib..."
lib = loadLib("test.dll")
echo "lib loaded!"
Both the asynchronous input checking and the loading of the lib work fine on their own, but in combination I encounter an issue where readLine suddenly blocks the main thread the moment loadLib is called. Any idea?
Hmm, it works for me on Linux with the latest git version of the compiler.
So, your problem is that lib loaded! is never called on Windows?
What version of Nim are you running?
Perhaps the issue was fixed in the latest git version. You should try, if it wasn't you should file a bug report.
Nim is 0.16.0
to be exact the issue shows up like this:
loading lib...
> now blocked by readLine until I press enter in the console
lib loaded!
@Serenitor
I tried your snippet exactly and it loaded immediately. Maybe because I made test.dll using gcc? Haven't tried vcc or using gcc in Linux yet.
alright, thanks a lot for testing. that's strange though, I'm on win10x64 and compile with gcc 6.3.0 (mingw-w64).
Could it be that it is connected to the contents of the lib file?
Can you maybe pass me your test.dll source @mashingan (and/or the binary)?
@Serenitor
Yes, it could be the lib of file that invoke some function when loaded and maybe that function has some blocking procedure.
In my test, I just simply made dummy function
/*
* compile with gcc in Windows (mingw64)
* $ gcc -shared -o test.dll test.c
*
* in Linux (bash in Windows 10)
* $ gcc -shared -fPIC -o test.so test.c
*/
#ifdef _WIN32
#include <windows.h>
unsigned int sleep (unsigned int seconds) {
Sleep(seconds * 1000); // Sleep needs in milliseconds while sleep needs in seconds
return 0;
}
#elif defined __unix__
#include <unistd.h>
#endif
int test() {
sleep(10); // this is blocking
return 10;
}
If you want to run/load the test function in Linux, somehow you have to hard-code the lib name to point to current directory (e.g. loadlib("./test.so")). I'm not sure why option -L. doesn't work. After looking around, you need to somehow edit LD_LIBRARY_PATH but since this is just test, that would be unnecessary :|
great, thanks, so that one works for me just as expected.
though my source for the lib will be written in Nim.
so it looks like I only get this issue when using a DLL generated from the Nim compiler, using something like proc --app:lib c test.nim
The gcc command generated by nim looks fine to me: gcc.exe -shared -o test.dll nimcache\stdlib_system.o nimcache\test.o
if you could confirm it, that would be much appreciated.
Creating shared lib with Nim works fine in my end and the lib loaded no problems.
The code is same with what I wrote in C
# compile: nim c --app:lib test.nim
from os import sleep
proc test(): int {.cdecl, exportc, dynlib.} =
sleep 10000 # blocking
10