Re: Getting GtkD working with OpenGL
On Thursday, 6 October 2016 at 13:35:01 UTC, Mike Parker wrote: So, change DerelictGL3.load to DerelictGL.load, then add a call to DerelictGL.reload after creating and activating the context. Thank you! That fixed the segmentation fault problem and the crash :) But I still struggle with the right Context... if I do something like this DerelictGL.load(); area.makeCurrent(); DerelictGL.reload(); I get an (runtime) error (on the terminal where I run my application): (LibraryTest:2984): Gtk-CRITICAL **: gtk_gl_area_make_current: assertion 'gtk_widget_get_realized (widget)' failed derelict.util.exception.DerelictException@gl3.d(85): DerelictGL3.reload failure: An OpenGL context is not currently active. [...] After all, I really don't know, what a GLContext is, what I need it for and how to use it. If somebody can explain it to me, I would be happy! I didn't find anything about it on the Internet, but I like to know, whats going on behind my code... I will keep on playing around with all the context functions, maybe I find something by accident that works xD
Re: Getting GtkD working with OpenGL
On Tuesday, 4 October 2016 at 17:00:34 UTC, Mike Wey wrote: Replace "import glgdk.GLContext;" with "import gdk.GLContext;" Hey Mike, you've been a great help so far! Thank you :) I thought now I am ready to draw something, but I struggle with the GLContext and GdkGlContext. Where do I get a valid Context, or how do I make it valid? My program crashes always with segmentation fault, as soon as I call a GL function except glClear. It must be a problem with the Context... Btw, what exactly is a GLContext and what is it used for? I am not used to it, since neither Qt nor glut uses or needs a GLContext-like structure. Would be great, if you see the error again... I think I am only missing an initialization function in my "initGL". I didn't find anything on the Internet. Here my code: import gtk.Main; import gtk.MainWindow; import gtk.GLArea; import gdk.GLContext; import derelict.opengl3.gl; import std.functional : toDelegate; GLContext initGL(GLArea area) { DerelictGL3.load(); /* Error happens somewhere here: */ GdkGLContext *gdkCon; /* where do I get a valid "struct GdkGLContext"?*/ GLContext context = new GLContext(gdkCon); /*needs GdkGLContext pointer for Initialization*/ context.realize(); /*which of these two functions do I need really, and why?*/ context.makeCurrent(); /* Runtime Warnings: */ /* Gdk-CRITICAL **: gdk_gl_context_realize:assertion 'GDK_IS_GL_CONTEXT (context)' failed */ /*same for ...make_current...*/ return context; } bool renderGL(GLContext context, GLArea area) { glClearColor (0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); /*Here the program crashes with Segmentation Fault (Some pointer is NULL)*/ glLoadIdentity(); glColor3f(1.0, 1.0, 0.0); glBegin(GL_TRIANGLES); glVertex3f(0, 0, -2); glVertex3f(1, 0, -2); glVertex3f(0, 1, -2); glEnd(); return true; } void main(string[] args) { Main.init(args); MainWindow win = new MainWindow("Hello GL"); GLArea area = new GLArea(); area.addOnCreateContext(toDelegate()); area.addOnRender(toDelegate()); //area.addOnResize(toDelegate()); win.add(area); win.showAll(); Main.run(); }
Re: Getting GtkD working with OpenGL
On Monday, 3 October 2016 at 18:00:53 UTC, Mike Wey wrote: The signal functions can be found in the gobject.Signals module. But you should use the GLArea.addOnCreateContext / addOnRender / addOnResize functions to attach a D delegate to the signal. You will still need to link with the OpenGL libraries or use someting like Derelict. Hi Mike, thanks for your fast answer again! I just read about this delegates and I liked the concept. I experimented with it for a while and read a bit on the Internet, but I still don't get it working... My minimal example looks like this: import gtk.Main; import gtk.MainWindow; import gtk.GLArea; import glgdk.GLContext; void main(string[] args) { bool render(GLContext context, GLArea area) { return true; } Main.init(args); MainWindow win = new MainWindow("Hello World"); GLArea area = new GLArea(); area.addOnRender(,cast(GConnectFlags)0); win.add(area); win.showAll(); Main.run(); } If I compile it, I get this error: $ dmd main.d -I/usr/local/include/d/gtkd-3 -L-lgtkd-3 main.d(27): Error: function gtk.GLArea.GLArea.addOnRender (bool delegate(GLContext, GLArea) dlg, GConnectFlags connectFlags = cast(GConnectFlags)0) is not callable using argument types (bool delegate(GLContext context, GLArea area), GConnectFlags) I cant see, what I am doing wrong... Someone else sees the error? Tomorrow I try to subclass the GLArea, if this works I am happy :) But I'd like to use the handler stuff. Ah, and I know now, that I have to link against the GL and GLU library, but which module do I have to import, to make the functions visible for the compiler? Or do I need another binding therefore?
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 17:56:46 UTC, ag0aep6g wrote: When you do precompile to a library, you can skip the compilation later. That can save time. True, linking with this library instead of compiling it every time I changed my code will save me a lot of time :)
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 17:45:55 UTC, Jonathan M Davis wrote: The import statement just tells the D compiler to pull in declarations for the symbols that it needs from those modules. It doesn't actually compile those modules. You still have to give them to the compiler (either all together or separately to generate .o/.obj files) in order to actually compile them. And anything that's not D (like a C/C++ library) still needs to be linked in just like it would be in C/C++. In C/C++, #including is not enough to compile everything into your code unless everything is in the header files (which it rarely is). For the files in your project, you have to compile every .c/.cpp file to generate the .o or .obj files that the linker then links into your program, and for the 3rd party stuff that's in a library you need to link in the library. Simply #including doesn't actually bring something like curl or gtk into your program. You also have to link it when generating your executable. It's basically the same thing with D. Every .d file in your project needs to be compiled so that it gets linked into your executable, and if you want to use 3rd party stuff, you have to link in the libraries just like you would with C/C++. The separation is perhaps a bit less clear in D, because you usually just use .d files for everything, whereas C/C++ have .h and .c/.cpp as separate files. D does have .di files for the cases where you need to hide your code, but they don't get used often. But when you do use a .di file, that's what gets imported rather than the .d file which contains the actual definitions, so in that case, the separation is clearer. Ah great, now I understand it :) I thought, import and include would work the same way (taking all the code in the .h or .d file and pasting it into the other file). But if import extracts only the definitions, it is clear, that you have to link against the library, or to add all the .d files to your source code. A big thank-you to all repliers for making things clear :D
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 13:51:28 UTC, Mike Parker wrote: // wrapfoo.d import foo; // import the foo module from above void myFunc(string s) { import std.string : toStringz; my_func(s.toStringz()); } Thank you for the example, Mike! And thanks to all others who support me with their answers! I didn't expect so much answers, the D community seems to be very helpful :) But there still is one thing, which I don't get: If I "import foo;" in my project, it will be compiled alongside. So there is no need for an extra library. Same should be for wrapfoo.d. If I "import wrapfoo;", I should just need the C-library "foo", and no D-library "food" right? To have a more practical example, I looked up the "header" of the GtkD gtk/Main.d file. There are functions exactly like you described: public static void init(ref string[] argv) { int argc = cast(int)argv.length; char** outargv = Str.toStringzArray(argv); gtk_init(, ); argv = Str.toStringArray(outargv, argc); } This function wraps the C-like gtk_init function to a D init function. The gtk_init function is the function from the GTK+ library, which is loaded in the gtkc/gtk.d file: Linker.link(gtk_init, "gtk_init", LIBRARY.GTK); Linker and link are defined in the gtkc/Loader.d So, why is it not enough just to "import gtk.Main"? What kind of code is inside the gtkd-3 library?
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 12:54:03 UTC, Adam D. Ruppe wrote: It is possible, you just need to match compilers with the library in C++, whereas C libraries don't need such an exact match. With your Qt library, you get a build of it that is compatible with the compiler you use to build your application (either compiling it yourself or getting it from an OS package repo where they did it for you for your OS version) Ah, so the Qt libraries are C++ libraries. And they have to be compiled with the same compiler (or at least with a compiler with the same specification) I use for my application? I didn't know that, but it makes sense to me. But if there would be 2 C++ compilers on my linux system which create 2 different API's, I would need the Qt library twice on my system? One for an application compiled with the one compiler, and the other library for an application compiled with the other compiler. Since I have only 1 Qt library on my system, all linux compilers must create compatible API's, right? Wrap the C functions inside D classes. So they write D code that calls the C functions, then you use their D code. Ok, this is the same what cym13 wanted to say, right? So you can use the advantages of D? But I don't get, why I have a gtkd-3 lib. Why can't I just link against the gtk-3 lib then? I have now the headers to use the nice D stuff, but the linking should be done against the C-compiled library.
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 12:15:10 UTC, rikki cattermole wrote: To use any kind of function you must declare it, plain and simple. Any c or c++ function/class is the very much same way. Now C++ types such as classes are highly limited in D since it doesn't ugh cross over all that well (it does some weird things). I don't know if we understand each other. You have to declare each function in the language you are programming, that is clear to me. So if you write in D, you need "D-Headers" (which are not called headers in D, i know). What do you mean with "Now C++ types such as classes are highly limited in D"? Why don't they "just" support them you ask? Yeah, that a D compiler can't read .h files is obvious to me :)
Re: Why using wrappers for D?
On Monday, 3 October 2016 at 12:12:44 UTC, Adam D. Ruppe wrote: A lot of people like the wrappers as being prettier to use since you can turn C functions into classes and such. gtkd is an example of that. Thanks for your fast answers :) Hm, I thing I am missing some fundamentals... I read a bit about creating libraries in C++, and I found out, this is not possible, because there is no definition of the API. So you need some C "factory methods" to load C++ classes. So is it possible now by D to load a class directly, or what do you mean by "turn C functions into classes"? Also, I used the Qt library a lot with C++. But although it is a library, I have access to all the classes, like " QWidget w = new QWidget();". There is no factory method used. (This confuses me now a bit...) If its too much to explain within some sentences, maybe you know something where I could read more about it? I did not find anything myself. But I really want to understand what's going on. Of course, it is simple, just bring over the necessary struct, constant, and function prototypes and it just works. I have to try it :D
Why using wrappers for D?
Hi All! The documentation of D (https://dlang.org/overview.html#compatibility) says: "Direct Access to C API's Not only does D have data types that correspond to C types, it provides direct access to C functions. There is no need to write wrapper functions, parameter swizzlers, nor code to copy aggregate members one by one." So, if there is no need for wrapper functions, why are there a lot of them? For example, GTK+ is a C library, with C-include files. Now there exists the GtkD (http://gtkd.org/) library, which describes itself as a wrapper of GTK+. GtkD contains the .d files (which I need for import, of course) and a seperate library (libgtkd-3.so). If D has direct Access to C API's, why do we need this the gtkd-3 lib, and not just use the gtk-3 lib? Furthermore, if there is an not very popular C library, where no wrapper function exists, would it possible to include it into a D project? Probably I have to transform all the .h to .d files, so i can "import" them instead of "include" them. But then, could I link against the C-library? I did not understand the concept of interaction between C and D, and I am a bit confused about wrapper functions and bindings for D now... Would be great if someone could make it a bit more clear to me :)
Re: Getting GtkD working with OpenGL
On Sunday, 18 September 2016 at 21:41:45 UTC, Mike Wey wrote: The demo still uses the old GtkGLExt binding, which usually isn't available in de distributions repositories. The newer GLArea is easier to use since it's part of GTK. As for the linker errors, you'll need to link with the OpenGL libraries: "-L-lGL -L-lGLU" Hey, thanks for your fast answer! I had a lot of other work to do, so I could only continue working on this project now. Yeah, that solved my problem :) Now it links. Although if I execute the program, it complains about the missing GtkGLExt library, like expected... Library load failed: libgdkglext-3.0.so.0 So I wanted to install this library from here: https://projects.gnome.org/gtkglext/download.html but the ./configure script tells me, No package 'pangox' found (pangox >= 1.0.0) I looked at the folder /usr/lib/x86_64-linux-gnu/ and there is a file called "libpangox-1.0.so.0.0.0". So I don't know, why this is not working... Anyway, I want to follow Mikes advice and use GLArea instead, so if there is not a quick fix available, lets skip the problems with the GtkGLExt library... But, sadly enough, I did not get GLArea working, too. The documentation https://developer.gnome.org/gtk3/stable/GtkGLArea.html says, I have to connect my render function to the widget like this: g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL); But, my compiler can't find the g_signal_connect method (and the GL Methods...): main.d(22): Error: undefined identifier 'g_signal_connect' main.d(39): Error: undefined identifier 'glClearColor' main.d(40): Error: undefined identifier 'glClear' There might some include files (or import files, as you say in D) missing, but I could not figure out, where to find them for D... Could you tell me, where this g_signal_connect method can be found? And what I have to include for the GL functionality? Simply "import gtk.GLArea;" does not do the trick... Btw, is g_signal_connect a GTK method? I intend to use my program platform independent, so if this is dependent on gnome, it would not be good. Or is there any other way to get the GLArea working? I am used to the Qt Libraries, where you create a QGLWidget and simply override the init and render functions. Thanks for reading this far, would be great if we could solve this problem :D
Re: Getting GtkD working with OpenGL
Here the code I actually wanted to compile (SimpleGL.d): /* * This file is part of gtkD. * * dui is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * dui is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with dui; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ module simpleGL.SimpleGL; private import gdk.Event; private import gtk.DrawingArea; private import gtk.Main; private import gtk.MainWindow; private import gtk.Widget; private import glgdk.GLConfig; private import glgdk.GLContext; private import glgdk.GLdInit; private import glgdk.GLWindow; private import glgtk.GLCapability; private import gtkglc.glgdktypes; private import gtkglc.gl; private import gtkglc.glu; /** * This is a Simple class extending the DrawingArea widget. * A really simple Demo illustrating OpenGL with GtkD * It uses the GLCapability mixin to add the GL capabilities to the widget. * This example is provided under the terms of the GPL License. * Note the initialization of the GLCapabilities on the constructor. * * @author p...@tuxfamily.org */ class SimpleGL : DrawingArea { GLfloat width; GLfloat height; /** need to include the mixin to add GL capabilities to this widget */ mixin GLCapability; /** * Construct a simple DrawingArea and sets the GLCapabilities */ this() { super(300, 300); setGlCapability(); // set the GL capabilities for this widget } /** * put any gl initializations here * returns true to consume the event */ void initGL() { resizeGL(null); } /** * This method is called every time the window must be paint or repaint * This is where you put the OpenGL call to draw something. * This method call be called directly by the application without an event object * to force redrawing of the scene. * returns true to consume the event */ bool drawGL() { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); gluLookAt(0, 0, 10, 0, 0, 0, 0, 1,0); //Set the camera position //Just Draw a tri-colored triangle glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glEnd(); return true; } /** * This method is called when the window is resized * returns true to consume the event */ bool resizeGL(Event event = null) { GLfloat w; GLfloat h; if ( event is null || event.type != GdkEventType.CONFIGURE ) { w = getWidth(); h = getHeight(); } else { w = event.configure.width; h = event.configure.height; } width = w; height = h; glViewport (0, 0, cast(int)w, cast(int)h); //Adjust the viewport according to new window dimensions /* * Update the projection Matrix accoding to the new dimension * and reset the OpenGL state to MODELVIEW */ glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective(20, w/h, 0.1, 10); glMatrixMode (GL_MODELVIEW); return true; } } void main(string[] args) { Main.init(args); GLdInit.init(args); SimpleGL simpleGL = new SimpleGL(); MainWindow window = new MainWindow("Simplest OpenGL Example"); window.add(simpleGL); window.showAll(); Main.run(); }
Getting GtkD working with OpenGL
Hi All! This weekend I explored Dlang and I think it's very promising. So I wanted to create some projects I've created with C++ already - for the sake of comparison. I wanted to create a new class which inherits from DrawingArea (from the Gtk library). This will be my OpenGL-Widget with functions like "drawGL", which I have to override. So I downloaded the "GtkD-3.3.0.zip" from here: http://gtkd.org/download.html and compiled it successfully (with "make all"). Now I've got the libraries gstreamerd-3, gtkd-3, gtkdgl-3, gtkdsv-3 and vted-3. I also got the module files for the import at "/usr/local/include/d/gtkd-3/", after I did a "make install". Now I tested a little example I found somewhere in the web, which looks like: import gtk.MainWindow; import gtk.Label; import gtk.Main; import gtk.GLArea; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow("Hello World"); GLArea area = new GLArea(); win.add(area); win.setDefaultSize(200, 100); win.showAll(); Main.run(); } This compiles fine and I get an empty black window. (I compiled with the options: "dmd main.d -I/usr/local/include/d/gtkd-3 -L/pathToLib/libgtkd-3.a") Now I scanned through the demos at the GtkD Library and I found one, that fits my needs perfectly. It is located at ".../GtkD-3.3.0/demos/gl/simple/SimpleGL.d" (I post the source code in an extra answer, since it is a bit lengthy...) This demo compiles fine (with "dmd main.d -c -I/...", -c tells the compiler not to link). But the linker gives an error here (command was: "dmd main.o -L/libgtkd-3.a -L/libgtkdgl-3.a ...", I linked to all the libs mentioned above). I get a very lengthy error message, and I cant figure out, why the reference to all the gl stuff is missing. Would be really great, if some one could give me a hint! Ah, yeah, just do avoid the answer "make it with dub!": Actually I did it also with dub and I get the same error messages... If you are interested, I can provide you also my .json file. But I like to know whats going on behind, so I prefer the way to install my libs manually. Would be great, if I get this working. $ dmd main.o -L/.../GtkD-3.3.0/libgtkd-3.a -L/.../GtkD-3.3.0/libgtkdgl-3.a -L/.../GtkD-3.3.0/libgstreamerd-3.a -L/.../GtkD-3.3.0/libgtkdsv-3.a -L/.../GtkD-3.3.0/libvted-3.a main.o: In function `_D8simpleGL8SimpleGL8SimpleGL8__mixin712realizeFrameMFC3gtk6Widget6WidgetZv': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin712realizeFrameMFC3gtk6Widget6WidgetZv+0xcf): undefined reference to `glFlush' main.o: In function `_D8simpleGL8SimpleGL8SimpleGL8__mixin79drawFrameMFC5cairo7Context7ContextC3gtk6Widget6WidgetZb': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin79drawFrameMFC5cairo7Context7ContextC3gtk6Widget6WidgetZb+0xc0): undefined reference to `glFlush' main.o: In function `_D8simpleGL8SimpleGL8SimpleGL8__mixin714configureFrameMFC3gdk5Event5EventC3gtk6Widget6WidgetZb': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin714configureFrameMFC3gdk5Event5EventC3gtk6Widget6WidgetZb+0x11a): undefined reference to `glFlush' main.o: In function `_D8simpleGL8SimpleGL8SimpleGL8__mixin78mapFrameMFC3gtk6Widget6WidgetZv': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin78mapFrameMFC3gtk6Widget6WidgetZv+0xbb): undefined reference to `glFlush' main.o: In function `_D8simpleGL8SimpleGL8SimpleGL8__mixin710unmapFrameMFC3gtk6Widget6WidgetZv': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin710unmapFrameMFC3gtk6Widget6WidgetZv+0xbb): undefined reference to `glFlush' main.o:main.d:(.text._D8simpleGL8SimpleGL8SimpleGL8__mixin715visibilityFrameMFC3gdk5Event5EventC3gtk6Widget6WidgetZb+0xc8): more undefined references to `glFlush' follow main.o: In function `_D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb': main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x45): undefined reference to `glClear' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x4a): undefined reference to `glLoadIdentity' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0xa9): undefined reference to `gluLookAt' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0xb7): undefined reference to `glBegin' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0xdb): undefined reference to `glColor3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0xff): undefined reference to `glVertex3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x123): undefined reference to `glColor3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x142): undefined reference to `glVertex3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x166): undefined reference to `glColor3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x18a): undefined reference to `glVertex3f' main.d:(.text._D8simpleGL8SimpleGL8SimpleGL6drawGLMFZb+0x18f): undefined reference to `glEnd' main.o: In function