GTK and libraries loading in Windows

39 views
Skip to first unread message

pocho

unread,
Jun 2, 2009, 1:35:36 PM6/2/09
to slate-language
Hi again, this is a fork of the other post, specifically refered to
Gtk and libraries loading

As we said...

> > > > > All this was in order to make it work in Windows XP[...]
>
> > I think you might have been the first to try gtk on windows. It's
> > fairly new code
>
> Well, it seems to be almost working. I've been investigating a bit
> more... in src/ui/glib/lib.slate we have
>
> GLib define: #Lib -> (
> ExternalInterface newForLibrary: 'glib-wrapper' primitives: #(
> (Void wrapper_g_object_connect_to_block_id(Pointer CString Int))"
>
> (Void wrapper_g_callback_queue_init())
> (Void wrapper_g_callback_queue_shutdown())
> (Pointer wrapper_g_callback_wait_next())
> (Void wrapper_g_callback_end(Pointer))
> (Int wrapper_g_callback_data_get_block_id(Pointer))
> (Int wrapper_g_callback_data_get_parameter_count(Pointer))
> (Pointer wrapper_g_callback_data_get_parameter_at(Pointer Int))
>
> (Boolean wrapper_g_type_is_fundamental(Int))
> (Int wrapper_g_type_fundamental(Int))
> (Int wrapper_g_type_from_instance(Pointer))
> (CString g_type_name(Int))
> ...
>
> Notice that loading fails when loading the first pure glib function
> (not wrappers, last line pasted), g_type_name, which makes me think it
> could load all wrappers, but then (I don't know why) searches glib-
> wrapper dll for g_type_name instead of looking in the correct place
> (gobject dll). Maybe there's a difference in steps needed to be
> carried when loading libraries needed by other libraries in Windows.
>

well... I think I found the answer. By debuggin slate in VS, I found
that my predictions were true. Slate is able to find glib-wrapper.dll
and even load all functions defined in glib-wrapper.c. The problem
comes from a diference of how symbols are searched in windows and
linux (done in external-library.c, lookupExternalLibraryPrimitive
(...)),


in line 83 you have

#ifdef WIN32
fn = (void *) GetProcAddress(h, symbol);
#else
fn = (void *) dlsym(h, symbol);
#endif

the problem is that, as you can read here,
http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html,
"... The dlsym() function shall search for the named symbol in all
objects loaded automatically as a result of loading the object
referenced by handle ."

but GetProcAddress used in windows doesn't (I wasn't able to find some
parametrized version to do this), so when you call GetProcAddress(glib-
wrapper handle, "g_type_name"), it just searches glib-wrapper.dll and
fails.

well.. I don't know how to solve this problem, but at least I think
I've given you a good enough description so that someone could fix it.
Also, I can send you the projects I had to create in VS to generate
the wrappers' dlls.

Bye.


Timmy Douglas

unread,
Jun 2, 2009, 5:49:43 PM6/2/09
to slate-language


On Jun 2, 1:35 pm, pocho <elpochodelage...@gmail.com> wrote:
> in line 83 you have
>
> #ifdef WIN32
>   fn = (void *) GetProcAddress(h, symbol);
> #else
>   fn = (void *) dlsym(h, symbol);
> #endif
>
> the problem is that, as you can read here,http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html,
> "... The dlsym() function shall search for the named symbol in all
> objects loaded automatically as a result of loading the object
> referenced by handle ."
>
> but GetProcAddress used in windows doesn't (I wasn't able to find some
> parametrized version to do this), so when you call GetProcAddress(glib-
> wrapper handle, "g_type_name"), it just searches glib-wrapper.dll and
> fails.
>
> well.. I don't know how to solve this problem, but at least I think
> I've given you a good enough description so that someone could fix it.
> Also, I can send you the projects I had to create in VS to generate
> the wrappers' dlls.

Yeah, Guille did this as a shortcut to not having to write wrapper
functions in his plugin to recall the actual gtk function. I should
have thought of that. On the other hand, would it make more sense for
someone to just do a native windows port instead of using gtk?

I believe the best short-term solution for this would be to add the
functions into the plugin source file in src/plugins with the same
signature but a different name and have them call the original gtk
function. If I had a windows box here I could do it but I don't so
hopefully someone else will be interested in working on it.




pocho

unread,
Jun 2, 2009, 11:20:48 PM6/2/09
to slate-language
Well, I'm doing that, but then another problem arrises..

when creating the wrappers, I can't name them exactly like gtk funcs
(because they would clash) so, I'm adding wrap_ before each name (like
this: "g_type_name" becomes "wrap_g_type_name"). The problem then is
that I have to modify ui/glib/init.slate to search for
wrap_q_type_name instead of q_type_name. But now, everything in .slate
files refers to g_type_name, so we get MethodNotFound everywhere. This
happens for each glib, gtk and gdk function. Do you have any quick fix
for that problem?

Timmy Douglas

unread,
Jun 2, 2009, 11:27:43 PM6/2/09
to slate-language
timmy@timmy-desktop:~/src/slate/cslatevm$ grep -rn 'g_type_name' src/
grep: src/plugins/.libs/gtk-wrapper.la: No such file or directory
grep: src/plugins/.libs/glib-wrapper.la: No such file or directory
grep: src/plugins/.libs/llvm-wrapper.la: No such file or directory
grep: src/plugins/.libs/gdk-wrapper.la: No such file or directory
src/ui/glib/lib.slate:16: (CString g_type_name(Int))
src/ui/glib/type.slate:33: GLib Lib primitives g_type_name
applyTo: {t type}

that's probably the easiest way to find all the matches. Sorry, but
you might have to manually find and replace the matches. Visual Studio
probably has a find and replace that can help you get all the source
files.

Since they have underscores in the name, you don't have to worry much
about them being used in other places.

Sorry for the inconvenience.

pocho

unread,
Jun 2, 2009, 11:35:52 PM6/2/09
to slate-language
actually I was thinking in renaming all method names (or slots? not
sure) of

Glib Lib primitives

so that everything whose name starts with 'wrap_' gets renamed (to the
original name, whitout the 'wrap_'). That could be done just after
loading the library, at the end of src/ui/glib/init.slate. Do you
think that's posible?

Timmy Douglas

unread,
Jun 3, 2009, 8:08:37 AM6/3/09
to slate-language
I don't know exactly what you mean... but I think the easiest way
would be to rename to:

src/ui/glib/lib.slate:16: (CString wrap_g_type_name
(Int))
src/ui/glib/type.slate:33: GLib Lib primitives wrap_g_type_name
applyTo: {t type}

and in src/plugins/glib.c or whatever you might have:

char* wrap_g_type_name(int arg) { return g_type_name(arg); }

pocho

unread,
Jun 3, 2009, 12:56:15 PM6/3/09
to slate-language
well my idea is to just to use this wrap_* names when loading, because
it's not just g_type_name that would need to be changed in each use
in .slate files, it's every glib primitive (and that's a looot). So,
the way to do that would be, after loading the wrappers, and before
anyone uses them, run some code that gathers all wrapped methods ands
copies them but without the 'wrap_':

GLib Library specs methods select: [ |:each| each selector beginsWith:
'wrap_'].

would get the methods to be renamed, now I lack the code to:

a) rename them to the same but without wrap_, and
b) add them to the specs.

doing this would make all this change transparent to the users of the
wrapped functions.

Timmy Douglas

unread,
Jun 3, 2009, 5:40:11 PM6/3/09
to slate-language
Oh, yeah that makes sense. In that case you could do something like:

GLib define: #BaseLib -> (
ExternalInterface newForLibrary: 'libglib' primitives: #(

(CString g_type_name(Int))
)
).

GLib BaseLib enable.

(We might have to modify the search path for dlopen/loadlibrary?)
In other words, put the real library name there and then call them
like

GLib BaseLib primitives g_type_name applyTo: {t type}


Perhaps there would be a way to put them in the lib namespace also so
you wouldn't have to change that too. But it might make more sense if
they were separated.

How is this approach?

pocho

unread,
Jun 4, 2009, 2:59:39 PM6/4/09
to slate-language
Well, I think I'm almost there... using that code, I was able to load
everything. Actually, I changed GLib Lib to GLib LibWrapper and let
GLib Lib be the one who has all glib functions. That allowed me to
leave most slate code unchanged. Also had to do the same with Gdk and
Gtk, and add GObject, which was used in some places.

But... doing load: 'src/ui/gtk/demo.slate' worked fine until the end,
all gtk, glib and gdk files were loaded. It took almost 8 minutes but
worked. Then it tryied to open something and exploded. I've got some
weird messages repeating everytime (had to close console because it
wouldn't stop repeating). This was too much for me, I'm clueless here.

this was the output, it kind of repeated this all the time.

------------------------------
fp: 853991
sp: 853985
ip: 40/48
result: 853966
method: 'newWithFlags:type:buttons:'
regs: 16
heap alloc: true
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (00000003) = <smallint value: 1 (0x1x)>
arg[2] (00000005) = <smallint value: 2 (0x2x)>
arg[3] (00000009) = <smallint value: 4 (0x4x)>
var[0] (014630B4)= ('Gtk MessageDialog')
var[1] (00000003)= <smallint value: 1 (0x1x)>
var[2] (00000005)= <smallint value: 2 (0x2x)>
var[3] (00000009)= <smallint value: 4 (0x4x)>
var[4] (0189D770)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[5] (00630100)= ('Oddball traits')
var[6] (00630100)= ('Oddball traits')
------------------------------
fp: 853962
sp: 853956
ip: 79/81
result: 853933
method: 'newQuestionMessage:'
regs: 20
heap alloc: false
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (0189D770) = ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[0] (00630100) = ('Oddball traits')
var[1] (013CC588) = ('MessageDialog') ('Symbol traits')
var[2] (000000B9) = <smallint value: 92 (0x92x)>
------------------------------
fp: 853931
sp: 853925
ip: 75/121
result: 853923
method: 'invokeDebugger'
regs: 25
heap alloc: true
arg[0] (0189D518) = ('MethodNotFound traits')
var[0] (0189D518)= ('MethodNotFound traits')
var[1] (0189D63C)= ('WriteStream traits')
var[2] (00630100)= ('Oddball traits')
var[3] (0189D770)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
------------------------------
fp: 853921
sp: 853915
ip: 7/9
result: 853914
method: 'defaultHandler'
regs: 3
heap alloc: false
arg[0] (0189D518) = ('MethodNotFound traits')
var[0] (0189D56C) = ('Set traits')
------------------------------
fp: 853905
sp: 853899
ip: 43/45
result: 853897
method: 'tryHandlers'
regs: 10
heap alloc: true
arg[0] (0189D518) = ('MethodNotFound traits')
var[0] (0189D518)= ('MethodNotFound traits')
var[1] (0189D56C)= ('Set traits')
------------------------------
fp: 853895
sp: 853889
ip: 7/9
result: 853885
method: 'signal'
regs: 3
heap alloc: false
arg[0] (0189D518) = ('MethodNotFound traits')
var[0] (0189D4E4) = ('Message traits')
------------------------------
fp: 853873
sp: 853867
ip: 73/75
result: 853856
method: 'notFoundOn:'
regs: 16
heap alloc: true
arg[0] (013C4060) = ('gtk_message_dialog_new') ('Symbol traits')
arg[1] (0189D490) = ('Array traits')
var[0] (013C4060)= ('gtk_message_dialog_new') ('Symbol traits')
var[1] (0189D490)= ('Array traits')
var[2] (00630100)= ('Oddball traits')
var[3] (0189D4E4)= ('Message traits')
var[4] (0189D518)= ('MethodNotFound traits')
------------------------------
fp: 853854
sp: 853848
ip: 22/58
result: 853845
method: ''
regs: 13
heap alloc: false
------------------------------
fp: 853843
sp: 853837
ip: 11/13
result: 853823
method: 'do'
regs: 4
heap alloc: false
arg[0] (0189D458) = ('Closure traits')
var[0] (00630100) = ('Oddball traits')
------------------------------
fp: 853821
sp: 853815
ip: 24/64
result: 853810
method: 'protectedDo:'
regs: 13
heap alloc: false
arg[0] (013ADEBC) = ('ExternalInterface traits')
arg[1] (0189D458) = ('Closure traits')
var[0] (00630100) = ('Oddball traits')
var[1] (01357554) = ('Lib') ('Symbol traits')
var[2] (00630100) = ('Oddball traits')
------------------------------
fp: 853799
sp: 853793
ip: 40/48
result: 853774
method: 'newWithFlags:type:buttons:'
regs: 16
heap alloc: true
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (00000003) = <smallint value: 1 (0x1x)>
arg[2] (00000005) = <smallint value: 2 (0x2x)>
arg[3] (00000009) = <smallint value: 4 (0x4x)>
var[0] (014630B4)= ('Gtk MessageDialog')
var[1] (00000003)= <smallint value: 1 (0x1x)>
var[2] (00000005)= <smallint value: 2 (0x2x)>
var[3] (00000009)= <smallint value: 4 (0x4x)>
var[4] (0189D384)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[5] (00630100)= ('Oddball traits')
var[6] (00630100)= ('Oddball traits')
------------------------------
fp: 853770
sp: 853764
ip: 79/81
result: 853741
method: 'newQuestionMessage:'
regs: 20
heap alloc: false
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (0189D384) = ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[0] (00630100) = ('Oddball traits')
var[1] (013CC588) = ('MessageDialog') ('Symbol traits')
var[2] (000000B9) = <smallint value: 92 (0x92x)>
------------------------------
fp: 853739
sp: 853733
ip: 75/121
result: 853731
method: 'invokeDebugger'
regs: 25
heap alloc: true
arg[0] (0189D12C) = ('MethodNotFound traits')
var[0] (0189D12C)= ('MethodNotFound traits')
var[1] (0189D250)= ('WriteStream traits')
var[2] (00630100)= ('Oddball traits')
var[3] (0189D384)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
------------------------------
fp: 853729
sp: 853723
ip: 7/9
result: 853722
method: 'defaultHandler'
regs: 3
heap alloc: false
arg[0] (0189D12C) = ('MethodNotFound traits')
var[0] (0189D180) = ('Set traits')
------------------------------
fp: 853713
sp: 853707
ip: 43/45
result: 853705
method: 'tryHandlers'
regs: 10
heap alloc: true
arg[0] (0189D12C) = ('MethodNotFound traits')
var[0] (0189D12C)= ('MethodNotFound traits')
var[1] (0189D180)= ('Set traits')
------------------------------
fp: 853703
sp: 853697
ip: 7/9
result: 853693
method: 'signal'
regs: 3
heap alloc: false
arg[0] (0189D12C) = ('MethodNotFound traits')
var[0] (0189D0F8) = ('Message traits')
------------------------------
fp: 853681
sp: 853675
ip: 73/75
result: 853664
method: 'notFoundOn:'
regs: 16
heap alloc: true
arg[0] (013C4060) = ('gtk_message_dialog_new') ('Symbol traits')
arg[1] (0189D0A4) = ('Array traits')
var[0] (013C4060)= ('gtk_message_dialog_new') ('Symbol traits')
var[1] (0189D0A4)= ('Array traits')
var[2] (00630100)= ('Oddball traits')
var[3] (0189D0F8)= ('Message traits')
var[4] (0189D12C)= ('MethodNotFound traits')
------------------------------
fp: 853662
sp: 853656
ip: 22/58
result: 853653
method: ''
regs: 13
heap alloc: false
------------------------------
fp: 853651
sp: 853645
ip: 11/13
result: 853631
method: 'do'
regs: 4
heap alloc: false
arg[0] (0189D06C) = ('Closure traits')
var[0] (00630100) = ('Oddball traits')
------------------------------
fp: 853629
sp: 853623
ip: 24/64
result: 853618
method: 'protectedDo:'
regs: 13
heap alloc: false
arg[0] (013ADEBC) = ('ExternalInterface traits')
arg[1] (0189D06C) = ('Closure traits')
var[0] (00630100) = ('Oddball traits')
var[1] (01357554) = ('Lib') ('Symbol traits')
var[2] (00630100) = ('Oddball traits')
------------------------------
fp: 853607
sp: 853601
ip: 40/48
result: 853582
method: 'newWithFlags:type:buttons:'
regs: 16
heap alloc: true
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (00000003) = <smallint value: 1 (0x1x)>
arg[2] (00000005) = <smallint value: 2 (0x2x)>
arg[3] (00000009) = <smallint value: 4 (0x4x)>
var[0] (014630B4)= ('Gtk MessageDialog')
var[1] (00000003)= <smallint value: 1 (0x1x)>
var[2] (00000005)= <smallint value: 2 (0x2x)>
var[3] (00000009)= <smallint value: 4 (0x4x)>
var[4] (0189CF98)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[5] (00630100)= ('Oddball traits')
var[6] (00630100)= ('Oddball traits')
------------------------------
fp: 853578
sp: 853572
ip: 79/81
result: 853549
method: 'newQuestionMessage:'
regs: 20
heap alloc: false
arg[0] (014630B4) = ('Gtk MessageDialog')
arg[1] (0189CF98) = ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')
var[0] (00630100) = ('Oddball traits')
var[1] (013CC588) = ('MessageDialog') ('Symbol traits')
var[2] (000000B9) = <smallint value: 92 (0x92x)>
------------------------------
fp: 853547
sp: 853541
ip: 75/121
result: 853539
method: 'invokeDebugger'
regs: 25
heap alloc: true
arg[0] (0189CD40) = ('MethodNotFound traits')
var[0] (0189CD40)= ('MethodNotFound traits')
var[1] (0189CE64)= ('WriteStream traits')
var[2] (00630100)= ('Oddball traits')
var[3] (0189CF98)= ('The method #gtk_message_dialog_new was not found
for the following arguments:\x0a{()}\x0aDebug it?') ('ASCIIString
traits')

Timmy Douglas

unread,
Jun 4, 2009, 5:26:54 PM6/4/09
to slate-language
Thanks for working on it.

It looks like an error happened earlier from the output you pasted.
The error caused you to enter the debugger but there is an error when
you enter the debugger which makes the debugger go in an endless loop.
Make sure you ported these correctly since it seems the function
wasn't found:

src/ui/gtk/messagedialog.slate:12: Gtk Lib primitives
gtk_message_dialog_new applyTo: {parentHandle. flags. type. buttons.
message }
src/ui/gtk/lib.slate:84: (Pointer gtk_message_dialog_new
(Pointer Int Int Int CString))

This is probably executed from code around:

src/ui/gtk/main.slate:11: c@(Condition traits) invokeDebugger [

Mark Haniford

unread,
Jun 4, 2009, 7:35:27 PM6/4/09
to slate-l...@googlegroups.com
Pocho, I for one, appreciate your efforts (especially on the windows
platform). As you pointed out, Slate has some unique properties as a
language. Once I win the lottery, I'll hire you, Timmy, and Brian to
work on Slate full time ;)

pocho

unread,
Jun 5, 2009, 7:26:01 PM6/5/09
to slate-language
jajaja I appreciate your offer but there's no way I'll become a full
time programmer!

pocho

unread,
Jun 8, 2009, 9:54:23 AM6/8/09
to slate-language
well, timmy has just committed some changes I did in order to make
this work in windows. Now if you try to open gtk in windows, you
should get a window open (that looks dead and won't respond, like this
http://img41.imageshack.us/img41/163/screenshotnwz.png ). While
debbugging slate vm in VS, I found that there were 2 threads running,
one stuck waiting here (I'm not 100% sure because i can't remember),

EXPORT CallbackData *wrapper_g_callback_wait_next(void) {
return (CallbackData *)g_async_queue_pop(callbackQueue);
}

and the other here, I think between gtk_main() and gdk_threads_leave
(),

void wrapper_gtk_main( void ) {
gdk_threads_enter(); //The book says to call this begore gtk_main
gtk_main();
gdk_threads_leave();
}

as I don't know what this does, and Gtk bundle doesn't come with
debbugging symbols, I can't go further. If someone could give a hand,
that would be nice. Meanwhile I may try to compile Gtk with VS, but
that will take a huge amount of time, so if this can be solved without
going through that pain I'll be really really happy.

I also have a question... as I was told there's no way of saving gtk
windows to be reopened later in slate, but is at least possible to
save an image with all Gtk libs loaded? As I said before, it takes
almost 8 minutes to load gtk so I don't want to do this loading
everytime I turn on the vm.

Bye,
pocho.

Brian T. Rice

unread,
Jun 8, 2009, 5:09:54 PM6/8/09
to slate-l...@googlegroups.com

On Jun 8, 2009, at 6:54 AM, pocho wrote:

> I also have a question... as I was told there's no way of saving gtk
> windows to be reopened later in slate, but is at least possible to
> save an image with all Gtk libs loaded? As I said before, it takes
> almost 8 minutes to load gtk so I don't want to do this loading
> everytime I turn on the vm.

Yes, because of all the libraries to be parsed, it's slow to load
everything, and we should be able to avoid this overhead as much as
possible. What ideally should happen is that external Gtk widgets/
resources could adopt or inherit the pattern of ExternalResource (also
used by File, Socket, Directory, and ExternalLibrary objects), in that
there is a "locator" attribute which stores some description of how to
recreate the resource, and then startup/shutdown methods construct and
teardown the actual objects in question. The ExternalResource also
keeps a "handle" attribute for the low-level identifier that the VM
gets and then passes into the image. ExternalResources also has a
parentResource attribute which is currently used for the
ExternalFunction-ExternalLibrary relationship but basically helps
determine the part-subpart dependency structure, in that the children
depend on the parent resource being enabled before they can be
(re)created and work.

In the window's case, the "locator" might be an array specifying
dimensions, and maybe a display tree of widget children along with
their dimensions and attributes. I'm hand-waving at this point, but
does this make sense as a way to think about the problem?

--
http://BrianTRice.com

Timmy Douglas

unread,
Jun 8, 2009, 6:24:41 PM6/8/09
to slate-language


On Jun 8, 9:54 am, pocho <elpochodelage...@gmail.com> wrote:
> I also have a question... as I was told there's no way of saving gtk
> windows to be reopened later in slate, but is at least possible to
> save an image with all Gtk libs loaded? As I said before, it takes
> almost 8 minutes to load gtk so I don't want to do this loading
> everytime I turn on the vm.

Yeah it should be possible and fairly easy to do. If you can't do it
by loading gtk/init.slate and then saving your image, then tell me.
After than (like demo.slate), you run this to start the gui:
Gtk Main do: [ Gtk Workspace new show ].

Currently, entering the gui is the point of no return. It should be a
fairly easy fix (for someone that understands gtk) to make it where
closing the last window puts you back into a slate prompt so that you
can save again. The reason you can't just save in the gui is because
the GUI code uses bytearrays with C pointers of gtk objects and if you
save a slate image in that code and have it resume (by starting slate
with that image), the resuming code will deref those invalid pointers
and crash.

Reply all
Reply to author
Forward
0 new messages