In order to use modern OpenGL functions above legacy version 1.1, a loading library is required (unless you manually load the function pointers from the GPU drivers yourself of course). If opengl32.dll only contains a software legacy OpenGL 1.1 implementation for windows, why is it still required to be linked to by loading libraries like GLEW or internally loaded by GLAD?
As alluded to in the comments above, openGL32.dll contains the method wglGetProcAddress. This is pretty much the only function that you need for openGL.
The loader libraries (e.g. glew, glad, et al) are basically a load of function pointers. Those function pointers need to be initialised at startup, hence needing to call glewInit, which will actually just make a load of calls to wglGetProcAddress.
Basically glew will essentially boil down to something along these lines internally:
// declare a function pointer type
typedef void (*glFlushPointer)();
// a global function pointer
glFlushPointer glFlush = 0;
#include <GL/gl.h> //< required for wglGetProcAddress
void glewInit() {
// now repeat this process for every GL function you need...
glFlush = (glFlushPointer)wglGetProcAddress("glFlush");
}
Related
I want to load some textures using glTexStorageXX(), but also fall back to glTexImageXX() if that feature isn't available to the platform.
Is there a way to check if those functions are available on a platform? I think glew.h might try to load the GL_ARB_texture_storage extensions into the same function pointer if using OpenGL 3.3, but I'm not sure how to check if it succeeded. Is it as simple as checking the function pointer, or is it more complicated?
(Also, I'm making some guesses at how glew.h works that might be wrong, it might not use function pointers and this might not be a run-time check I can make? If so, would I just... need to compile executables for different versions of OpenGL?)
if (glTexStorage2D) {
// ... calls that assume all glTexStorageXX also exist,
// ... either as core functions or as ARB extensions
} else {
// ... calls that fallback to glTexImage2D() and such.
}
You need to check if the OpenGL extension is supported. The number of extensions supported by the GL implementation can be called up with glGetIntegerv(GL_NUM_EXTENSIONS, ...).
The name of an extension can be queried with glGetStringi(GL_EXTENSIONS, ...).
Read the extensions into a std::set
#include <set>
#include <string>
GLint no_of_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &no_of_extensions);
std::set<std::string> ogl_extensions;
for (int i = 0; i < no_of_extensions; ++i)
ogl_extensions.insert((const char*)glGetStringi(GL_EXTENSIONS, i));
Check if an extension is supported:
bool texture_storage =
ogl_extensions.find("GL_ARB_texture_storage") != ogl_extensions.end();
glTexStorage2D is in core since OpenGL version 4.2. So if you've created at least an OpenGL 4.2 context, there's no need to look for the extension.
When an extension is supported, all of the features and functions specified in the extension specification are supported. (see GL_ARB_texture_storage)
GLEW makes this a little easier because it provides a Boolean state for each extension.
(see GLEW - Checking for Extensions) e.g.:
if (GLEW_ARB_texture_storage)
{
// [...]
}
I have come across something similar to this piece of code today.
In A.h:
class A { blah blah blah }
#define CREATE_A_FUNC_NAME ("CreateA")
extern "C" A* CreateA(void);
typedef A* (*funcCreateA)(void);
In main.cpp:
void* handle = dlopen("libA.so", RTLD_LAZY);
funcCreateA func = (funcCreateA)dlsym(handle, CREATE_A_FUNC_NAME);
A* a = func();
Now obviously A.h is only the header for declarations and all its implementations are stored in libA.so.
I have tested that if I set up my project correctly, meaning the lib is correctly linked, I can simply do A* a = CreateA() to get the pointer to a newly created A instance. Hence here come the questions. Why go through so much hassle to achieve something simple as one function call? What is this kind of technology or technique called? What are the pros and cons? When should I use this technique? Thanks!
The main reasons to use dlsym rather than linking to the DSO directly:
you want to provide a plugin mechanism with your app, so you need to be able to load a DSO on the fly (The plugins aren't known to the linker when you built the exe). The simplest approach for this is to add some virtual base class (I'm assuming 'A' has some virtual methods?), and then export a creator method with "C" linkage (which disables C++ name mangling). It looks as though that's the intent here?
You may have code optimised for a specific CPU instruction set (i.e. at startup of a game engine, check which is the latest instruction set the CPU supports, load the relevant SSE or AVX library at runtime, and then call the methods optimised for that particular CPU).
In rare cases you might want to 'unload' some heavy code to free up more memory on the device. This happens quite a lot on Android/iOS and consoles (e.g. releasing the shader compiler after all the shaders have been compiled).
It's worth noting that if you link to the DSO directly, under the hood, the linker will simply insert dlsym/dlopen code at app start up, which will automatically load the DSO and resolve the symbols.
Out of curiosity, what exactly happens when an application compiled with the MSVCR is loaded, resp. how does the loader of Windows actually initialize the CRT? For what I have gathered so far, when the program as well as all the imported libraries are loaded into memory and all relocations are done, the CRT startup code (_CRT_INIT()?) initializes all global initializers in the .CRT$XC* sections and calls the user defined main() function. I hope this is correct so far.
But let's assume, for the sake of explanation, a program that is not using the MSVCR (e.g. an application built with Cygwin GCC or other compilers) tries to load a library at runtime, requiring the CRT, using a custom loader/runtime linker, so no LoadLibrary() involved. How would the loader/linker has to handle CRT initialization? Would it have to manually initialize all "objects" in said sections, does it have to do something else to make the internal wiring of the library work properly, or would it have to just call _CRT_INIT() (which unpractically is defined in the runtime itself and not exported anywhere as far as I am aware). Would this mix-up even work in any way, assuming that the non-CRT application and the CRT-library would not pass any objects, exceptions and things the like between them?
I would be very interested in finding out, because I can't quite make out what the CRT has an effect on the actual loading process...
Any information is very appreciated, thanks!
The entrypoint for an executable image is selected with the /ENTRY linker option. The defaults it uses are documented well in the MSDN Library article. They are the CRT entrypoint.
If you want to replace the CRT then either pick the same name or use the /ENTRY option explicitly when you link. You'll also need /NODEFAULTLIB to prevent it from linking the regular .lib
Each library compiled against the C++ runtime is calling _DllMainCRTStartup when it's loaded. _DllMainCRTStartup calls _CRT_INIT, which initializes the C/C++ run-time library and invokes C++ constructors on static, non-local variables.
The PE format contains an optional header that has a slot called 'addressofentrypoint', this slot calls a function that will call _DllMainCRTStartup which fires the initialization chain.
after _DllMainCRTStartup finishes the initialization phase it will call your own implemented DllMain() function.
When you learn about programming, someone will tell you that "the first thing that happens is that the code runs in main. But that's a bit like when you learn about atoms in School, they are fairly well organized and operate acorrding to strict rules. If you later go to a Nuclear/Particle Physics class at university, those simple/strict rules are much more detailed and don't always apply, etc.
When you link a C or C++ program the CRT contains some code something like this:
start()
{
CRT_init();
...
Global_Object_Constructors();
...
exit(main());
}
So the initialization is done by the C runtime library itself, BEFORE it calls your main.
A DLL has a DllMain that is executed by LoadLibrary() - this is responsible for initializing/creating global objects in the DLL, and if you don't use LoadLibrary() [e.g. loading the DLL into memory yourself] then you would have to ensure that objects are created and initialized.
I want to do application, which can be compiled with external modules, for example like in php. In php you can load modules in runtime, or compile php with modules together, so modules are available without loading in runtime. But i don't understand how this can be done. If i have module in module.c and there is one function, called say_hello, how can i register it to main application, if you understand what i mean?
/* module.c */
#include <stdio.h>
// here register say_hello function, but how, if i can't in global scope
// call another function?
void say_hello()
{
printf("hello!");
}
If i compile all that files(main app + modules) together, there isn't some reference to say_hello function from main app, because it is called only if user call it in its code. So how can i say to my app, hey, there is say_hello function, if someone want to call it, you know it exists.
EDIT1: I need to have something like table at runtime, where i can see if user called function exists (have C equivavent). Header files doesn't help to me.
EDIT2: My app is interpret for my script langugage.
EDIT3: If someone call function in php, php interpret must know that function exists. I know about dynamic linking and if .so or .dll is loaded, then some start routine is called and you can simple register function in that dll, so php interpret can see, if some module registred for example function called "say_hello". But if i want compile php with for example gd support, then how gd functions are registred to some php function list, hashtable or whatever?
I guess what you are looking for is dynamic libraries (we call runtime loadable modules as dynamic/shared libraries in C and in the OS world, in general). Take, for example, Pidgin which supports plugins to extend it's functionalities. It gives a particular interface to it's plugin-makers to abide by, say functions to register, load, unload and use, which the plugins will have to follow.
When the program loads, it looks for such dynamic libraries in it's plugins directory, if present, it'll load and use it, else it'll skip exposing the functionality. The reason why an interface is needed is that since different modules can have different functionalities which are unknown uptil runtime, an app. has to have a common, agreed-upon way of "talking" to it's plugins/modules.
Every C program can be linked to a static or a dynamic library; static will copy the code from the library to the said program, there by leaving no dependencies for the program to run, while linking to a dynamic library expects the dynamic library to be present when the program is launched. A third way of doing it, is not to link to a DLL, but just asking the OS to perform a load operation of the library. If this succeeds, then the dynamic module is used, else ignored. The functionality which the dynamic library should perform is exposed to the user, only if the load call succeeds.
It is to be noted that this is a operating system provided feature and it has nothing to do with the language used (C or C++ or Python doesn't matter here); as far as C is concered, the compiler still links to known code i.e. code which is available # compile time. This is the reason for different operating system, one needs to write different code to load a dynamic module. Even more, the file type/format of syuch libraries vary from system to system. In Linux it's called shared objects (.so), in Mac it's called dynamic libraries (.dylib) and in Windows as Dynamic link libraries (.dll).
C is not interpreted language. So you need linking, you may want static linking or dynamic linking.
Program building consists of 2 major phases: compiling and linking. During compiling all c-files are translated into machine code, leaving called functions unresolved (obj or o files). Then linker merges all these files into one executable, resolving what was unresolved.
This is static linking. Linked module becomes integral part of executable.
Dynamic linking is platform specific. Under windows these are DLLs. You should issue a system call to load DLL after which you will be able to call functions from it.
What you need is dynamic library. Let's first take a look at the example provided in the Linux manpage of dlopen(3):
/* Load the math library, and print the cosine of 2.0: */
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libm.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is a workaround. */
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
There's also a C++ dlopen mini HOWTO.
For more general information about dynamic loading, start from the wikipedia page first.
I think it is impossible, if i understand what you mean. Because it is compiled language.
I want to modify the glBindTexture() function to keep track of the previously binded texture ID's. At the moment i just created new function for it, but then i realised that if i use other codes that use glBindTexture: then my whole system might go down to toilet.
So how do i do it?
Edit: Now when i thought it, checking if i should bind texture or not is quite useless since opengl probably does this already. But i still need to keep track on the previously used texture.
As Andreas is saying in the comment, you should check this is necessary. Still, if you want to do such a thing, and you use gnu linker (you don't specify the operating system) you could use the linker option:
--wrap glBindTexture
(if given directly to gcc you should write):
-Wl,--wrap,glBindTexture
As this is done at linker stage, you can use your new function with an already existing library (edit: by 'library' I mean some existing code which you can recompile but which you wouldn't want to modify).
The code for the 'replacement' function will look like:
void * __wrap_glBindTexture (GLenum target, GLuint texture) {
printf ("glBindTexture wrapper\n");
return __real_glBindTexture (target,texture);
}
You actually can do this. Take a look at LD_PRELOAD. Create a shared library that defines glBindTexture. To call the original implementation from within the wrapper, dlopen the real OpenGL library and use dlsym to call the right function from there.
Now have all client code LD_PRELOAD your shared lib so that their OpenGL calls go to your wrapper.
This is the most common method of intercepting and modifying calls to shared libraries.
You can intercept and replace all calls to glBindTexture. To do this you need to create your own OpenGL dll which intercepts all OpenGL function calls, does the bookkeeping you want and then forward the function calls to the real OpenGL dll. This is a lot of work so I would defintely think twice before going down this route...
Programs like GLIntercept work like this.
One possibility is to use a macro to replace existing calls to glBindTexture:
#define glBindTexture(target, texture) myGlBindTexture(target, texture)
Then in you code, where you want to ensure against using the macro, you surround the name with parentheses:
(glBindTexture)(someTarget, someTexture);
A function-like macro is only replace where the name is followed immediately by an open-parenthesis, so this prevents macro expansion.
Since this is a macro, it will only affect source code compiled with the macro visible, not an existing DLL, static library, etc.
I haven't ever worked with OpenGL, so not knowing anything about that function, here's my best guess. You would want to replace the glBindTexture function call with your new function's call anywhere it occurs in your code. If you use library functions that will call glBindTexture internally, then you should probably figure out a way to reverse what glBindTexture does. Then, anytime you call something that binds a texture, you can immediately call your reversal function to undo its changes.
The driver WON'T do it, it's in the spec. YOU have to ensure that you don't bind the same texture twice, so it's a good idea.
However, it's even a better idea to separate the concerns : let the low-level openGL deal with its low-level stuff, and your (thin, thick, as you want) abstraction layer do the higher-level stuff.
So, create a oglWrapper::BindTexture function that does the if(), but you should not play around with LD, even if this is technically possible.
[EDIT] In fact, it's not in the ogl spec, but still.
In general, the approaches have been catalogued under the heading of "seams", as popularized in M. Feather's 2004 book Working Effectively with Legacy Code. The book focuses on finding seams in a monolith application to isolate parts of it and put them under automated testing.
Feathers' seams can be found in the following places
compiler
__attribute__ ((ifunc in GCC, https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
preprocessor
change what gets used with a #define
linker
-Wl,--wrap,func_xyz
linking order, first found symbol gets used, program can delegate using dlsym(RTLD_NEXT, ...)
the binary format has a Procedure Linkage Table which can be modified by the program itself when it runs
in Java, much can be achieved in the JVM, see for example Mockito
language features
function pointers, this can actually be done so as to add no syntactic overhead at point of call!
object inheritance: inherit, override, call super()
sources:
https://www.informit.com/articles/article.aspx?p=359417&seqNum=3
https://www.cute-test.com/guides/mocking-with-cute/