I have this test program for the official iup library, which links to a iup.dll on Windows 10 or libiup.so on Linux (Raspbian - RaspberryPi):
import os
import iup
var
arguments = os.commandLineParams()
c_args: cstringArray
arg_length = arguments.len.cint
for i in 0..arguments.len-1:
c_args[i] = cstring(arguments[i])
discard iup.open(addr(arg_length), addr(c_args))
var font_dialog = fontDlg()
font_dialog.popup(IUP_CURRENT, IUP_CURRENT) # <-- a SIGSEGV happens here on Linux
font_dialog.destroy()
iup.close()
The signatures for all the used procedures and types are:
type
Ihandle = object
PIhandle* = ptr Ihandle
proc open*(argc: ptr cint, argv: ptr cstringArray): cint {.importc: "IupOpen", cdecl, dynlib: dllname.}
proc fontDlg*: PIhandle {.importc: "IupFontDlg", dynlib: dllname, cdecl.}
proc popup*(ih: PIhandle, x, y: cint): cint {.importc: "IupPopup", cdecl, dynlib: dllname, discardable.}
proc destroy*(ih: PIhandle) {.importc: "IupDestroy", cdecl, dynlib: dllname.}
proc close*() {.importc: "IupClose", cdecl, dynlib: dllname.}
and it was compiled on both platforms with: nim c iuptest.nim On Windows it works without problems, but on Linux it throws a SIGSEGV error at the marked line above.
Now first I thought it was a library problem, so I made an equivalent program in C:
#include <stdlib.h>
#include <iup.h>
int main(int argc, char **argv)
{
IupOpen(&argc, &argv);
Ihandle* dlg = IupFontDlg();
IupPopup(dlg, IUP_CURRENT, IUP_CURRENT);
IupDestroy(dlg);
IupClose();
return EXIT_SUCCESS;
}
and compiled it with on Linux with: gcc iuptest.c -o iuptest -I/PATH/TO/iup.h -liup. But the C program also works without problems! The C prototypes for the used functions and types (defined in iup.h) are:
typedef struct Ihandle_ Ihandle;
int IupOpen (int *argc, char ***argv);
Ihandle* IupFontDlg(void);
int IupPopup (Ihandle* ih, int x, int y);
void IupDestroy (Ihandle* ih);
void IupClose (void);
Can someone tell me if I am missing something or if the programs are not equivalent?
Thanks, Matic
Great bug report -- I would really like to see such fine reports for gintro!
Is that Nim iup API really that ugly as you coded it in your example? Looks worse than your C example :-(
Unfortunately I can not really help you -- but you have done nearly all to find the problem yourself: Just compare the Nim C file in nimcache with your working C example. Maybe one remark -- why discard result of iup.open() ? Maybe better compare it with result from C code?
@Stefan_Salewski Thanks. That was what I was afraid of, digging through the C code, but I guess there is no way around it.
@mashingan I tried adding the executable name, but no change.
This seems to be an almost identical problem: https://trac.wxwidgets.org/ticket/16820 The relevant post is:
So, after a long investigation, I figured out what's going on here.
It turns out that GTK loads some function addresses at runtime using dlsym().
In this particular case, it is trying to load the function pango_font_face_get_type().
It does so after doing a dlopen(NULL). In the case of wxGTK, the GTK and dependent libraries have
been loaded globally, so it finds the symbol. In the case of wxPython, since the Python extension
modules are loaded locally (ie, python does dlopen(RTLD_LOCAL)), GTK can't find the symbol.
I'm looking at having wxPython load its extension modules with RTLD_GLOBAL as a possible solution.
The C code above does not use the dlopen function to link to the library, while in Nim this seems to be the way symbols are loaded. The relevant code from the generated C files is:
Dl_179323_ = (tyProc_r29aessx9bSQ6WUVhzFLO83g) nimGetProcAddr(TM_lHAxv2o2PoBLNZ9at1j7Ffg_2, "IupOpen");
Dl_179251_ = (tyProc_NzboHqZVJcbdtVGYrOosXQ) nimGetProcAddr(TM_lHAxv2o2PoBLNZ9at1j7Ffg_2, "IupFontDlg");
Dl_179426_ = (tyProc_YsPh3gbdjC9aWnl5GwfE11g) nimGetProcAddr(TM_lHAxv2o2PoBLNZ9at1j7Ffg_2, "IupPopup");
Dl_179379_ = (tyProc_32w2ZypAyMWuajvi2Jt79cg) nimGetProcAddr(TM_lHAxv2o2PoBLNZ9at1j7Ffg_2, "IupDestroy");
Dl_179329_ = (tyProc_ln4kdL5W9bbX4a1xl8nnVXQ) nimGetProcAddr(TM_lHAxv2o2PoBLNZ9at1j7Ffg_2, "IupClose");
N_NIMCALL(void*, nimLoadLibrary)(NimStringDesc* path) {
void* result;
result = (void*)0;
result = dlopen((path ? path->data : (NCSTRING)""), ((int) 2));
return result;
}
Does this information help anyone? Because I do not have enough experience with this.
Great that you have found something.
I can remember a different problem with Nim's use of dlopen, but I guess it is not really related to your problem:
https://mail.gnome.org/archives/gtk-list/2015-March/msg00016.html
It is a quite similar problem. Just tried it on Lubuntu x86 and it throws the same error.
The whole error message is:
$ ./test
(test:6635): Gtk-WARNING **: Unknown type PangoFontFamily specified in treemodel model
(test:6635): Gtk-WARNING **: Unknown type PangoFontFace specified in treemodel model
(test:6635): Gtk-WARNING **: /home/pi/gtk+3.0-3.22.11/./gtk/gtkliststore.c:516: Invalid type (null)
(test:6635): Gtk-WARNING **: /home/pi/gtk+3.0-3.22.11/./gtk/gtkliststore.c:516: Invalid type (null)
(test:6635): GLib-GObject-CRITICAL **: g_value_type_transformable: assertion 'G_TYPE_IS_VALUE (src_type)' failed
(shutdown:6635): GLib-GObject-CRITICAL **: g_value_type_transformable: assertion 'G_TYPE_IS_VALUE (src_type)' failed
(test:6635): GLib-GObject-WARNING **: /build/glib2.0-F5w919/glib2.0-2.50.3/./gobject/gtype.c:4264: type id '0' is invalid
(test:6635): GLib-GObject-WARNING **: can't peek value table for type '<invalid>' which is not currently referenced
Traceback (most recent call last)
test.nim(26) shutdown
test.nim(21) main
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
It has to be something to do with GTK's dynamic loading of libraries. Does anyone have experience with this?