www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Need extern (C) interface even though using Derelict GLFW

reply "WhatMeWorry" <kheaser gmail.com> writes:
I've been translating C++, OpenGL, and GLUT code into D, Derelict 
OpenGL, and Derelict GLFW using:

import derelict.opengl3.gl3;
import derelict.glfw3.glfw3;

auto window = glfwCreateWindow(800, 600, "Shaders", null, null);

etc.


Things have been going well. I then tried to implement window 
resizing with a callback function and the 
glfwSetWindowSizeCallback() statement.


void windowResizeCallback(GLFWwindow* window, int width, int 
height)
{
     glViewport(0, 0, width, height);
}

and

glfwSetWindowSizeCallback(window, &windowResizeCallback);


however, I kept getting the following compiler error:
Error	1	Error: function pointer glfwSetWindowSizeCallback 
(GLFWwindow*, extern (C) void function(GLFWwindow*, int, int) 
nothrow)
is not callable using argument types (GLFWwindow*, void 
function(GLFWwindow* window, int width, int height))

Well, I was able to get it to compile and work by adding the 
following "decoration"

extern (C) nothrow
{
     void windowResizeCallback(GLFWwindow* window, int width, int 
height)
     {
         glViewport(0, 0, width, height);
     }
}


Now it resizes the screen successfully, but I feel like I've 
failed by using extern (C) nothrow. Shouldn't Derelict GLFW be 
providing a D interface?

Maybe GLFW callback functions can't handled through Derelict GLFW?
Jan 03 2015
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 4/01/2015 5:34 p.m., WhatMeWorry wrote:
 I've been translating C++, OpenGL, and GLUT code into D, Derelict
 OpenGL, and Derelict GLFW using:

 import derelict.opengl3.gl3;
 import derelict.glfw3.glfw3;

 auto window = glfwCreateWindow(800, 600, "Shaders", null, null);

 etc.


 Things have been going well. I then tried to implement window resizing
 with a callback function and the glfwSetWindowSizeCallback() statement.


 void windowResizeCallback(GLFWwindow* window, int width, int height)
 {
      glViewport(0, 0, width, height);
 }

 and

 glfwSetWindowSizeCallback(window, &windowResizeCallback);


 however, I kept getting the following compiler error:
 Error    1    Error: function pointer glfwSetWindowSizeCallback
 (GLFWwindow*, extern (C) void function(GLFWwindow*, int, int) nothrow)
 is not callable using argument types (GLFWwindow*, void
 function(GLFWwindow* window, int width, int height))

 Well, I was able to get it to compile and work by adding the following
 "decoration"

 extern (C) nothrow
 {
      void windowResizeCallback(GLFWwindow* window, int width, int height)
      {
          glViewport(0, 0, width, height);
      }
 }


 Now it resizes the screen successfully, but I feel like I've failed by
 using extern (C) nothrow. Shouldn't Derelict GLFW be providing a D
 interface?

 Maybe GLFW callback functions can't handled through Derelict GLFW?
No this is correct code. Derelict projects are just bindings. Which means the c equivalent in D. Nothing more nothing less.
Jan 03 2015
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On 1/4/2015 1:34 PM, WhatMeWorry wrote:

 Now it resizes the screen successfully, but I feel like I've failed by
 using extern (C) nothrow. Shouldn't Derelict GLFW be providing a D
 interface?

 Maybe GLFW callback functions can't handled through Derelict GLFW?
Derelict provides direct bindings, not wrappers. Any of the Derelict packages can be used as the core of a wrapper that provides a more D-like API, but that's beyond the scope of the Derelict project.
Jan 04 2015
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On 1/4/2015 1:34 PM, WhatMeWorry wrote:

 Maybe GLFW callback functions can't handled through Derelict GLFW?
And just to be clear, because the pointers to the callback functions are being passed to a C API, they *have* to be extern( C ) -- i.e. they have to have the same calling convention that the C library expects. If the library functions used the stdcall calling convention rather than cdecl, then the callbacks would have to be extern( Windows ). So even a wrapper that allows you to pass D delegates or function pointers would still have to internally give GLFW a pointer to a function with the proper calling convention.
Jan 04 2015
parent reply "WhatMeWorry" <kheaser gmail.com> writes:
On Sunday, 4 January 2015 at 09:02:48 UTC, Mike Parker wrote:
 On 1/4/2015 1:34 PM, WhatMeWorry wrote:

 Maybe GLFW callback functions can't handled through Derelict 
 GLFW?
And just to be clear, because the pointers to the callback functions are being passed to a C API, they *have* to be extern( C ) -- i.e. they have to have the same calling convention that the C library expects. If the library functions used the stdcall calling convention rather than cdecl, then the callbacks would have to be extern( Windows ). So even a wrapper that allows you to pass D delegates or function pointers would still have to internally give GLFW a pointer to a function with the proper calling convention.
Thanks for the replies. I felt like I was creating a kludge. I have to confess that the above paragraph is pretty much incomprehensible to me. Except for "function pointers" the rest of the terms I have seen before, but can't really make out into a meaningful whole. Are they some extremely simple tutorials on bindings and wrappers? Something with lots of code examples.
Jan 04 2015
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 5/01/2015 9:30 a.m., WhatMeWorry wrote:
 On Sunday, 4 January 2015 at 09:02:48 UTC, Mike Parker wrote:
 On 1/4/2015 1:34 PM, WhatMeWorry wrote:

 Maybe GLFW callback functions can't handled through Derelict GLFW?
And just to be clear, because the pointers to the callback functions are being passed to a C API, they *have* to be extern( C ) -- i.e. they have to have the same calling convention that the C library expects. If the library functions used the stdcall calling convention rather than cdecl, then the callbacks would have to be extern( Windows ). So even a wrapper that allows you to pass D delegates or function pointers would still have to internally give GLFW a pointer to a function with the proper calling convention.
Thanks for the replies. I felt like I was creating a kludge. I have to confess that the above paragraph is pretty much incomprehensible to me. Except for "function pointers" the rest of the terms I have seen before, but can't really make out into a meaningful whole. Are they some extremely simple tutorials on bindings and wrappers? Something with lots of code examples.
I'll use luad as an example. Luad has both bindings and a wrapper to lua in it. Primarily you will use the wrapper. The bindings provide access directly to the c api. The wrapper makes the API nice to use in D. A binding is not meant to be nice to use. It is meant to be equivalent to the original.
Jan 04 2015
prev sibling parent "Mike Parker" <aldacron gmail.com> writes:
 Are they some extremely simple tutorials on bindings and 
 wrappers? Something with lots of code examples.
I don't think it's a subject that warrants a tutorial. There's not that much to it. Consider: // capi.h void do_something( const char *str ); // capi.d -- this is a binding extern( C ) void do_something( const( char )* str ); // capiwrapper.d -- this is a wrapper void doSomething( string str ) { import std.string : toStringz; do_something( str.toStringz() ); } That's all there is to it. The binding allows you to call C functions from D. The wrapper adds a more convenient D interface on top of the C function. Of course, there are numerous details to consider when implementing a binding (some of which you can see at [1]), but you generally don't need to worry about them as a user. There are exceptions, though, when you need to be aware of what's going on. One of those is when implementing callbacks. All you really need to understand is that the calling convention of the C functions may not be the same as that of D functions. That's why the C function above is decorated with extern( C ) -- it uses the cdecl calling convention (see [2] for an explanation of different x86 calling conventions). So any callbacks you pass into the API need to be of the same calling convention, because they are actually being called on the C side, not the D side. [1] http://dlang.org/interfaceToC.html [2] http://en.wikipedia.org/wiki/X86_calling_conventions
Jan 04 2015