Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28603 Discussions

Help for compilation of F03GL with IVF

glantoin
Beginner
1,491 Views
Hello all !

I am a PhD student and I would like to compile the F03GL interface (developed by Anthony Stone and Aleksandar Donev) in Visual Studio 2005 and IVF 11 (on Windows) for my research (I want to plot graphics with OpenGL in Fortran). F03GL uses the C Interoperability features of Fortran 2003 and binds to the C interface for OpenGL. However I am encountering some problems. Here is what I am doing:
- first I compile the interface source code files f03gl_gl.f90, f03gl_glu.f90, OpenGL_freeglut.f90, OpenGL_gl.f90, OpenGL_glu.f90, GLUT_fonts.c to obtain the corresponding object files
- then I include those files in a Visual Fortran project, along with one test example (sphere.f90 for instance). I also make sure that the linker links to the Windows Opengl libraries (I found those libraries in one of the directories of Visual Studio: OpenGL32.lib, GLU32.lib, GLAux.lib). I also added FreeGLUT.lib I compiled myself before to use FreeGLUT.

But when I try to compile the whole thing, I get linker errors, for instance
error LNK2019: unresolved external symbol _glClear referenced in function _display sphere.obj
error LNK2019: unresolved external symbol _glutInit referenced in function _OPENGL_GLUT. OpenGL_freeglut.obj

Basically all the opengl and glut functions cannot be found by the linker... But I'm sure I'm including the opengl libraries in the relevant properties of the project.

Do you have an idea of what the problem might be ? Maybe you encountered the same kind of problem before. I am really stuck, I don't know what to do... I don't want to use the standard f90GL interface library because I need to use freeGLUT instead of GLUT.

Thanks a lot in advance !

Gregory
0 Kudos
14 Replies
Steven_L_Intel1
Employee
1,491 Views
I had not heard before of f03gl nor freeglut but am pleased to do so now. You say you are sure you included all the necessary libraries but perhaps you are mistaken. Attach the buildlog.htm from a build that failed. I'll want to see on the link line the gl and glut libraries.
0 Kudos
glantoin
Beginner
1,491 Views
Hello Steve,

Thanks a lot for your reply ! Attached is the buildLog. I think the gl and glut libraries are there (OpenGL32.lib GLU32.lib GLAux.lib FREEGLUT.lib)

Gregory
0 Kudos
Steven_L_Intel1
Employee
1,491 Views
Ok. Initially, it looks to me as if Freeglut's DLL build assumes that it should use STDCALL for all of its routines. The freeglut.f90 module, though, uses BIND(C) for all the routines, which causes the default to be C. Curiously, the static library build assumes default conventions, matching what Intel Fortran wants.

Try this. On line 77 of freeglut_std.h, replace:

# define FGAPIENTRY __stdcall

with:

# define FGAPIENTRY

Then rebuild freeglut.

This will help with the glut calls, but not the gl or glu calls. I don't have an instant fix for you regarding that. It seems that the developers of f03gl have not taken the vagaries of IA32 Windows into account - this won't be an issue anywhere else.
0 Kudos
glantoin
Beginner
1,491 Views
Ok Steve I understand, thanks for all your efforts ! I also think it's a mismatch between conventions used by the
compiler and the libraries... Not sure how to fix the issue with gl and glu libraries either... Any fix ideas are welcome, even if they are not easy :)

Gregory
0 Kudos
Steven_L_Intel1
Employee
1,491 Views
In the case of the gl and glu libraries, it's a mismatch between the interfaces declared by f03gl and the Windows OpenGL routines. I'd have to spend more time looking at it to see if that could be resolved.

I'll note that if you build for x64, this problem will disappear.
0 Kudos
Steven_L_Intel1
Employee
1,491 Views
I took another look - one would have to rewrite the declarations in the OpenGL_xx.f90 modules to reflect IA-32 Windows calling conventions for the OpenGL routines provided by the Win32 API. Before someone jumps in and suggests /iface:cvf, I'll say that this won't work, as the BIND(C) overrides that.

I believe that this all would work on x64 (haven't tried that myself.)
0 Kudos
glantoin
Beginner
1,491 Views
Thanks again Steve !! I'll try first to see if I can make this work on a Win64 machine. Then I'll check if I can find someone to modify the source code somehow for Win32.

Gregory
0 Kudos
glantoin
Beginner
1,491 Views
Hello !

Regarding a Fortran interface of OpenGL that incorporates freeGLUT, I found an alternative to F03GL. It can be used in Windows 32 using G95. The steps are:
- g95 OpenGLw.f90 -S (to compile the interface source code as a mod file)
- g95.exe -mrtd -fno-underscoring sphere.f90 -o sphere -Wl,%windir%/system32/opengl32.dll,%windir%/system32/glu32.dll,%windir%/system32/fglut32.dll (where sphere.f90 is the test example)
Here for freeglut, callbacks were changed infreeglut_internal.h to allowfor stdcall calling convention:
typedef void (* FGC
becomes --> typedef void (__stdcall * FGC

So that sounds great and with G95 it's indeed working. But when I am trying to use IVF 11 and Visual Studio 2005 (still in Windows 32), I am still having trouble with unresolved external symbols... I switched the calling convention to STDCALL bit this does not help. Maybe I am not linking the dlls right ? There are opengl32.dll, glu32.dll and fglut32.dll. How can you link those dlls in Visual Studio ? If I try to specify them in the 'Additional Dependency' option of the Linker, there are errors: for instance,
fatal error LNK1107: invalid or corrupt file: cannot read at 0x270 opengl32.dll

I assume if it's working with G95, it should also work in IVF (with some minor changes) ? Or are those two compilers very different ?

Thanks a lot in advance !

Gregory
0 Kudos
Steven_L_Intel1
Employee
1,491 Views
The compilers are indeed different, but I'm having trouble understanding what you did. Are you trying to use IVF to link to something created by G95?
0 Kudos
glantoin
Beginner
1,491 Views
Hello Steve,

I'm trying to compile in IVF a code (the g95gl interface) that can be compiled in G95 (I tried it, it's indeed working in G95). I want to compile everything in IVF.

I was just able to make some progress. I was able to compile everything by keeping # define FGAPIENTRY __stdcall in freeglut_std.h, and for the bindings I write for instance bind(C,name='glClear@4') because that's what is actually written in the openGL libraries. That's a little tedious though because I have to find the bitnumber of the stdcall of each opengl routine.

So now it's compiling but the issue is that the graphic is displayed for 1s and then an error message shows up:
forrtl: severe(157): Program Exception - access violation
OPENGL32.dll 5ED00003 Unkwown

I talked to some people and someone suggested I should make callbacks as cdecl instead of stdcall since it seems I have a stack problem... But I don't know how I could do that in that case... Is cdecl the C/ref calling convention of IVF ? When I switch to C/ref calling convention, the problem is still there...

Thanks a lot for any insight !

Gregory
0 Kudos
Steven_L_Intel1
Employee
1,492 Views
Quoting - glantoin
I write for instance bind(C,name='glClear@4') because that's what is actually written in the openGL libraries.

Don't do that! It will cause stack corruption.

I would have to dig in to these packages to fully understand what a solution might be. The key point is that on 32-bit Windows, the OpenGL routines AND callbacks from OpenGL use the STDCALL convention. In IVF, at least, you cannot use BIND(C) for STDCALL routines. Instead, you must remove the BIND(C) attribute and then add a directive of the form:

!DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"glClear" :: glClear

in the interface body, for each gl and glu routine. Any callbacks you write must also have !DEC$ ATTRIBUTES STDCALL, REFERENCE in them. Failure to do this will result in stack corruption. You'd need a similar directive visible to any reference to the callback routine.

I have no idea what G95 is doing here - I'd expect it to have similar issues to IVF, compounded by what I think are its lack of facilities for creating individual STDCALL interfaces.

I'd love to take the time to work out a solution for you, but I just don't have the cycles right now. I suggest that you study the OpenGL samples provided by IVF to see how things are generally done regarding callbacks.
0 Kudos
glantoin
Beginner
1,492 Views
Hello Steve !!

I was finally able to make it work !! For the OpenGL routines, as you said, we must use the !DEC$ ATTRIBUTES syntax. However, for the callbacks, adding !DEC$ ATTRIBUTES STDCALL, REFERENCE is not working (stack issues). Instead I simply write bind(c) and everything works fine. I think this comes from the fact that the callbacks must be made as cdecl (?).
So for instance I do something like that:

[cpp]interface
 subroutine glutDisplayFunc(fun)
 !DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"glutDisplayFunc" :: glutDisplayFunc
  interface
   subroutine fun() bind(c)
   end subroutine fun
  end interface
 end subroutine glutDisplayFunc
end interface[/cpp]
And in the main program I also add bind(c) next to the callback.

Again, thanks a lot Steve, I would not have been able to do it without you :)

Gregory
0 Kudos
Steven_L_Intel1
Employee
1,492 Views
glut callbacks probably should be C - and you would not even need BIND(C). But any gl or glu callbacks will need STDCALL.
0 Kudos
glantoin
Beginner
1,492 Views
glut callbacks probably should be C - and you would not even need BIND(C). But any gl or glu callbacks will need STDCALL.

Oh Steve, I see! glut callbacks do not need BIND(C) indeed. And I will be careful with the gl and glu callbacks!

Thanks again for everything,

Gregory
0 Kudos
Reply