import iup
discard iup.open(nil,nil)
var cs : cstring = "*.txt"
echo iup.getFile(cs)
iup.close()
Program crashes before show the getFile result: SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Success if press the cancel button in file dialog.
(Windows 7, iup30.dll)
@juanv Right, sorry about that, forgot to check.
This works:
First change the signature of getFile in iup.nim to
proc getFile*(arq: ptr char): cint
and then try this:
import iup
discard iup.open(nil,nil)
var char_array: array[0..1000, char]
char_array[0] = '.'
char_array[1] = '.'
char_array[2] = '/'
char_array[3] = 'd'
char_array[4] = 'o'
char_array[5] = 'c'
char_array[6] = 's'
char_array[7] = '/'
char_array[8] = '*'
char_array[9] = '.'
char_array[10] = 't'
char_array[11] = 'x'
char_array[12] = 't'
var ptr_to_char_array = addr(char_array[0])
echo iup.getFile(ptr_to_char_array)
var end_char = 0
for i in 0..char_array.len-1:
if char_array[i] == '\0':
end_char = i - 1
break
echo $char_array[0 .. end_char]
iup.close()
I have no idea how to preallocate memory for a cstring, so it would work for cstrings. Maybe someone else can help?Sorry, I don't understand it.
I have the feeling that your code does basically the same as the code in the initial post.
For my Nim 0.19 on LinuxAMD64 the cstring seems to be allocated fine.
May your compiler version include a already fixed bug?
Note that generally we use plain Nim strings in our code, Nim strings get converted automatically to cstrings when passed to a proc which expects c string.
Can you post the original signature of your iup wrapper getFile() proc.
Hey @StefanSalewski The original signature is:
proc getFile*(arq: cstring): cint
and the C prototype is:
int IupGetFile(char *arq);
The problem might be because the function writes the selected file name back into arq, but I have no idea. I tried
proc getFile*(arq: var cstring): cint
but nothing changed.The problem might be because the function writes the selected file name back into arq
Great work!
That behaviour is uncommon, but indeed stated in IUP docs! What should work is allocating a large string with newString(4048) and then assigning chars one by one, or maybe assigning string first, and then calling setLen() with large size. But such a low level interface in IUP is really an ugly trap.
@Stefan_Salewski Excellent, it works with string:
import iup
discard iup.open(nil,nil)
var
str : string = newString(1024)
i: int = 0
for ch in "../docs/*.txt":
str[i] = ch
i += 1
echo iup.getFile(str)
echo str
iup.close()
But even this works with string like this:
import iup
discard iup.open(nil,nil)
var
str : string = "../docs/*.txt"
echo iup.getFile(str)
echo str
iup.close()
the only thing is it cuts the reply to len("../docs/*.txt")!
But why doesn't it work with cstring??? It's weird to see a signature proc getFile*(arq: cstring): cint, then when using cstring it doesn't work while it works with string. I know the whole concept is a bad way of passing data around, but still, it's very confusing, it should also work with cstring!
Well this one seems the best to me:
import iup, strutils
discard iup.open(nil,nil)
var str : string = "../docs/*.txt\0".alignleft(4096, padding=' ')
echo iup.getFile(str)
echo str.strip()
iup.close()
the only thing is it cuts the reply to len("../docs/.txt")!
Are you sure that iup lib cuts it? From
https://github.com/nim-lang/iup/blob/master/iup.nim
proc getFile*(arq: cstring): cint {.
importc: "IupGetFile", dynlib: dllname, cdecl.}
I see no change that iup can cut it. Well iup sees the "0" char as end of supplied string, but iup does not know that buffer may be restricted to this size.
My assumption is, that you watched result from echo output -- and well echo knows string size because its get a Nim string!
When you ask why it works with Nim string and not with cstring: Of course both is absolutely no clean code, iup docs say that getFile may use a buffer of up to 4096 bytes, while actual buffer of Nim strings generally is smaller. Maybe when Nim allocates a Nim string, its buffer is large enough for most iup lib results, with some luck. Maybe for cstrings Nim allocates a smaller buffer by default, what would make sense, because cstrings are generally more used as constants, while Nim strings are more often used with append or concatenation operations.