I am developing hobby opengl3 engine and I decided to make a new .dll build of it. It uses GLEW to get opengl3 functions from GPU. I've successfully builded it about 5 months ago, but now I've changed a lot and it doesn't want to get working.
So the .dll builds perfectly (windows7, mingw).
I've made a simple program and it crashes on first call to glCreateProgram which is runned by code from mylib.dll.
in pseudocode:
#include "mylib.hpp"
int main(){
std::cout << (void*)glCreateProgram << "\n";
// displays 0 as glCreateProgram haven't been loaded yet
myspace::Window* = new SDL2BasedWindow(...);
//this constructor is from my .dll and calls glewInit() which returns GLEW_OK
std::cout << (void*)glCreateProgram << "\n";
//this displays proper address
int testGLEW= glCreateProgram();
std::cout << "glCreateProgram from main: " << testGLEW<< "\n";
//this displays 1 which means valid call to glCreateProgram
window->runApplication(new Application(...));
//Application is user-defined class, it further creates myspace::ShaderProgram
//which is imported from my .dll (part of my engine) which then calls
//glCreateProgram in it's initialisation
//(it is first call to any function which should be initialized by GLEW if we count only code imported from mylib.dll)
}
//in ShaderProgram constructor:
std::cout << "trying to call glCreateProgram, address: ";
std::cout << (void*)glCreateProgram << "\n"; //this displays 0 (!)
int id = glCreateProgram(); //this ends execution with SIGSEGV
printf("created program: %d\n", id); //so this one is never called
So my question is, why GLEW works only in code which is not imported from my .dll and how can I fix it?
Btw I've checked nm mylib.dll ant it contains glCreateProgram and other glew dependent functions, I also use #define GLEW_STATIC both in .dll and program that uses this .dll
Thanks for your help!
#define GLEW_STATIC is used to build a static library or executable.
To build a .dll use #define GLEW_BUILD instead.
Related
I'm attempting to debug some very opaque issues with DLLs in Unreal on a CI machine (see Unreal: Diagnosing why Windows cannot load a DLL for more information). glu32.dll seems to be the DLL at which the Unreal process falls over, and as Windows Server doesn't contain all the graphics-related DLLs that normal Windows 10 does, I was recommended to upload certain DLLs from my machine/Microsoft redistributables in order to make sure the Unreal build process could run.
For sanity purposes, I've written a small utility program to test whether glu32.dll on my machine can be dynamically loaded and can have its functions called correctly. I'm planning to run this executable on the troublesome CI machine soon to see what happens.
The code for the program is below:
#include <windows.h>
#include <iostream>
#include <GL/gl.h>
extern "C"
{
typedef const GLubyte* (__stdcall *ErrorStringFunc)(GLenum error);
}
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage: GLU32Loader.exe <path to glu32.dll>" << std::endl;
return 1;
}
const char* path = argv[1];
std::cout << "Attempting to load: " << path << std::endl;
HMODULE dllHandle = LoadLibraryA(path);
if (!dllHandle)
{
std::cerr << "Could not load " << path << std::endl;
return 1;
}
std::cout << "Successfully loaded DLL: 0x" << dllHandle << std::endl;
const char* funcName = "gluErrorString";
std::cout << "Looking up function: " << funcName << std::endl;
ErrorStringFunc func = reinterpret_cast<ErrorStringFunc>(GetProcAddress(dllHandle, funcName));
if (func)
{
std::cout << "Successfully loaded function: 0x" << func << std::endl;
const GLubyte* str = (*func)(100902);
std::cout << "Error string for value 100902: \"" << str << "\" (0x" << static_cast<const void*>(str) << ")" << std::endl;
}
else
{
std::cerr << "Failed to load function " << funcName << std::endl;
}
FreeLibrary(dllHandle);
return 0;
}
When I run the executable and point it to glu32.dll in the System32 folder, I get expected output:
> GLU32Loader.exe "C:\Windows\System32\glu32.dll"
Attempting to load: C:\Windows\System32\glu32.dll
Successfully loaded DLL: 0x00007FFC7A350000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC7A35C650
Error string for value 100902: "out of memory" (0x000001E5757F51D0)
However, if I copy the DLL to my desktop and run the program again, although the DLL and function appear to be loaded, the string returned from the function is empty:
> GLU32Loader.exe "C:\Users\Jonathan\Desktop\glu32.dll"
Attempting to load: C:\Users\Jonathan\Desktop\glu32.dll
Successfully loaded DLL: 0x00007FFC8DDB0000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC8DDBC650
Error string for value 100902: "" (0x0000025C5236E520)
Why would this be? It's exactly the same DLL, just in a different folder, and I would have thought that any other dependent DLLs that it references should still be available because they're all in System32. Is there some mystical property of Windows DLLs that I'm not familiar with that might cause this to happen?
This is an example of why one shall not mess around with system DLLs.
The DLL in question, like many Microsoft DLLs, uses MUI (Multilingual User Interface).
If you look at its resources, it has no resources except a MUI type resource, pointing to a folder containing the corresponding .mui file, which contains its actual (internationalized) resources.
So, if you still want to copy it, at least also copy the corresponding .mui file:
System32\glu32.dll → <my_files>\glu32.dll
System32\en-US\glu32.dll.mui → <my_files>\en-US\glu32.dll.mui
The en-US part may be different on your system depending on the default locale.
EDIT: I saw only now from your log that you didn't rename the file. Then I'm not sure what it can be. I'll leave this explanation up anyway because it would also be what happens if one were to rename that file, so maybe it is helpful to someone else...
It seems to me as if you renamed the DLL file (not just loaded it from another location but with another filename as well).
glu32.dll doesn't like to be renamed, because in some places code like GetModuleHandle("glu32.dll") is used instead of saving the hInstance received in DllMain into a global variable and using that handle (which is what should have been done, but unfortunately it isn't what Microsoft did). If you rename the DLL, this call will return NULL. Now unfortunately there also isn't much error handling going on in glu32 in that case.
The error strings are stored in global arrays of some sort, but they are lazy-loaded there from string table resources. The first time you call gluErrorString, the error strings are loaded using LoadString which takes the hInstance of the DLL. With the renamed DLL, this will be the bogus NULL handle, and calling LoadString(NULL, ...) will return 0, indicating an error. Normally the number returned is the length of the string. glu32 doesn't handle the zero case in any special way and just copies the zero characters to the array and happily returns an empty string to you at the end.
I'm developing an OpenGL application using the sb6::application framework provided by SuperBible v6, and although it always works fine on my computer (even when I run the executable outside of my DE), no one else who I send it to can get it to run. It can't be an issue with OpenGL versions, since my friend has v4.2. (I have v4.3, but it's an extremely rudimentary program so I highly doubt I've done anything exclusive to v4.3) It might have to do with a missing file since the window just closes instantly when he starts it, but I can't figure out what file. It might be a .dll or something (I've assumed that I can just put any needed .dlls in the same folder as the executable) but I haven't been able to find out which one. I got my friend to run DependencyWalker and I specifically tracked down and sent him the ones that DependencyWalker said he was missing, and there was still no improvement.
SuperBible has absolutely no documentation on the sb6::application class and doesn't give any information about how to set up a project to be portable. Or if it does I haven't been able to find it even after days of searching.
Not sure which parts of the code are relevant to post, but here are the init() and startup() functions from the sb6::application class.
void init()
{
// Redirect output to this file.
//freopen("myoutput.txt", "w", stdout);
ready = false;
static const char title[] = "Forkits";
sb6::application::init();
memcpy(info.title, title, sizeof(title));
}
void save_viewport_size()
{
// Get the size of the window
glGetIntegerv(GL_VIEWPORT, m_viewport);
std::cout << m_viewport[0] << " " << m_viewport[1] << " " << m_viewport[2] << " " << m_viewport[3] << std::endl;
}
void startup(void)
{
// Check version
GLint version = 0;
//glGetFloatv(GL_VERSION, &version);
//glGetIntegerv(GL_VERSION, &version);
//std::cout << "Version number " << glGetString(GL_VERSION) << std::endl;
//printf("%s %s\n", glGetString(GL_RENDERER), glGetString(GL_VERSION));
// Save the size of the initial viewport
glGetIntegerv(GL_VIEWPORT, m_viewport);
std::cout << m_viewport[0] << " " << m_viewport[1] << " " << m_viewport[2] << " " << m_viewport[3] << std::endl;
program = glCreateProgram();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
print_shader_log(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
print_shader_log(fs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
print_linker_log(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Set parameters
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// Set up alpha blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ready = true;
flag_running = true;
int init_success = Forkits::init(&sprites);
logic = new std::thread(old_main);
}
You're right, you should just be able to put the .dlls in the same directory as the executable and it'll work. It's possible that sb6 is reliant on other .dlls that you have but your friend doesn't. Or more likely, your friend's .dlls are out of date. That is one route of investigation. It is interesting that the window opens up successfully, and then closes. To me, that points to a problem setting up your OpenGL context. Can you post the code that you call to set up OpenGL?
Another, and in my opinion, better route to take would be to remove sb6 from your application entirely and switch to another, more portable application framework. Sb6 is only intended for practice, if you want a more robust framework I would switch. Since you've only done a small project using sb6, now is also an excellent time to change over because the code changes would be minimal and (relatively :)) painless. Here are a few libraries I suggest:
SDL - My personal favorite. It'll do everything from setting up a window, handling input, networking, playing sounds, and even threading. And it (claims) to be completely portable. Be warned, however. They just went through a major update (1.2 to 2.0) and the documentation hasn't completely caught up yet.
GLFW - If you're making a dedicated OpenGL application, this might be a better option. Since it's built from the ground up to work with OpenGL (unlike SDL, which first and foremost is a windowing framework and doesn't care what you put in the windows) it's faster to set up to work with OpenGL.
SFML - Appears to be a varient of SDL. To be honest, I haven't used this one before, but if you like it, tell me how it is!
There are others out there as well, but these are the big three I've heard of. Let me know if you have any questions about running them.
I'm currently working with SDL2 and GLFW3 to create some OpenGL game. Initializing and using GLFW3 is no problem; I'm using GLFW3 for creating the OpenGL context, window, key input etc. and SDL2 for loading images to SDLSurfaces and then converting them to OpenGL textures, but, unlike GLFW3, SDL2 fails to initialize. My initialization code looks like this:
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
It always returns -1 and quits the main function. Does anyone know why this could happen?
The problem
The problem is not with SDL. SDL actually initializes completely fine. The problem is how you check if the initialization succeeded. Take a look at the documentation for SDL_Init()
Returns 0 on success or a negative error code on failure; call
SDL_GetError() for more information.
In your code code
if (!SDL_Init(SDL_INIT_EVERYTHING)) return -1;
In the if, the SDL_Init(SDL_INIT_EVERYTHING) part will return 0, which evaluates to false but it still means that SDL was successfully initialized. The ! in front, means the entire if will evaluate to true, and -1 will be returned.
Solution
A better soltion is to check if it's equal to 0 and if it does fail, used SDL_GetError() to print the error.
if ( SDL_Init(SDL_INIT_EVERYTHING) != 0 )
{
std::cout << "Error : " << SDL_GetError() << std::endl;
return -1;
}
I am on Ubuntu, writing an application using OpenGL, GLEW and GLFW. I am using Eclipse as my IDE, and am having problems when trying to use functions such as glGenRenderbuffer. I have a very similar structure set up under Windows but can't get it to work on Linux.
I am linking to the libraries glfw and GLEW. I am able to compile and run parts of my application and can initialize both GLFW and GLEW. From these test runs I learn the following:
OpenGL version: 4.2.0 NVIDIA 304.64
Using GLEW 1.6.0
However, I can't get the function glGenRenderbuffer (or other framebuffer functions) to compile. I have tried adding both EXT and ARB to the name, as well as playing around with glex.h without any luck. As far as I know, the purpose of GLEW is to handle all extension issues, right?
The source file (VolumeRenderer.cpp) includes are done like this:
#include <glm/gtc/matrix_transform.hpp>
#include <VolumeRenderer.h>
#include <GL/glew.h>
#include <GL/glfw.h>
Further down, I am trying to use the function like this (only partially complete function, of course):
bool VolumeRenderer::InitFramebuffers()
{
glGenRenderbuffers(1, &renderBufferObject_);
return true;
}
All I get is "function 'glGenRenderBuffers' could not be resolved".
Looking in the GL/glew.h header I am including, I found the following lines among others:
#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT)
But the compiler still can't find the function. Is there anything I have forgotten, or maybe some tests and checks I can run to see what is happening?
Alright, so I got it to work by basically copying my Eclipse project file by file into a new, empty project. However, I did some other things before that. First, I moved around the includes as suggested in the helpful comments. I also removed things like glm. No success! Then I made a simple project in Eclipse with one single .cpp file, and linked to glfw and GLEW:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#include <cstdlib>
int main()
{
if (glfwInit() != GL_TRUE) {
std::cout << "glfwInit() failed\n";
exit(1);
}
if (!glfwOpenWindow(800, 600, 8 , 8, 8, 8, 8, 8, GLFW_WINDOW)) {
std::cout << "glfwOpenWindow() failed\n";
exit(1);
}
char *glVersion = (char*)glGetString(GL_VERSION);
if (glVersion) {
std::cout << "OpenGL version: " << glVersion << "\n";
}
GLenum err = glewInit();
if (err != GLEW_OK) {
std::cout << "GLEW init failed: " << glewGetErrorString(err) << "\n";
exit(1);
} else {
std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << "\n";
}
GLuint buf;
glGenRenderbuffers(1, &buf);
exit(0);
}
That worked like a charm. I then tried to recreate my old problem by making another project with a similar file and include structure, and it seemed to work fine too. I then started a third, empty project where I simply made exact copies of the files that were originally giving me trouble. Now I have an exact copy of the original project (that now had the include order changed) with the exact same libraries linked to it, and it works. I still don't know what happened but I suspect that my project in Eclipse got messed up somehow, and never recovered even though I made some changes.
I want to ask question about how to call VB.NET DLL from C++ program
I have tried many times to call VB.NET DLL file from C++ and it is working fine but the problem is I can't call the function of VB.NET DLL file ( I can only load the VB.NET DLL file)
in VB.NET DLL I have the following code:
Public Function example_function1(ByVal i As Integer) As Integer
Return 3
End Function
Public Function example_function2(ByVal i As Integer) As Integer
Return 3
End Function
============================
My C++ Code is:
typedef int (__stdcall *ptf_test_func_1_type)(int);
typedef int (__stdcall *ptf_test_func_2_type)(int*);
int i =1;
HINSTANCE dll_instance = LoadLibrary("DLLs7.dll");
int main()
{
if(dll_instance !=NULL)
{
printf("The DLLs file has been Loaded \n");
cout << GetLastError() << endl;
ptf_test_func_1_type p_func1=(ptf_test_func_1_type)GetProcAddress(dll_instance,"Class1::example_function1");
ptf_test_func_2_type p_func2=(ptf_test_func_2_type)GetProcAddress(dll_instance,"Class1::example_function2");
// Function No 1 //
if (p_func1 != NULL)
{
cout << "\nThe function number 1 is " << p_func1(i) << endl;
}
else
{
cout << "\nFailed" << endl;
cout << GetLastError() << endl;
}
// Function No 2 //
if (p_func2 != NULL)
{
cout << "\nThe function number 2 is" << p_func2(&i) << endl;
}
else
{
cout << "\nFailed" << endl;
cout << GetLastError() << endl;
}
}
else
{
printf("\nDLLs file Load Error");
cout << GetLastError() << endl;
}
cout << GetLastError() << endl;
return(0);
}
My following steps is:
1) I have Created VB.NET DLL.
2) I have Created a new application visual C++ and selected "win32 console application"
3) I have written the code to call the DLL and the functions (as you can see in the above)
did I miss anything in the steps or code because I can call VB.NET DLL file but I can't call the VB.NET DLL function
as you can see I have written the GETLASTERRIR() to find the ERROR
cout << GetLastError() << endl;
but I found this Error 127 in function when failed and 203 in the call DLL file
can anyone help me
Thank you very much
Regards
Since your vb assembly needs a totally different runtime than the 'native' executable, you will need to use some layer in between. This layer may be COM.
You can expose your assembly to the COM subsystem by it's 'ComVisible' property. Then, you should register the assembly to expose it to COM 'subscribers'.
Only then you can #import the assembly namespace from your c++ code.
Note: this is a very brief version of an msdn article "How to call a managed DLL from native Visual C++ code"
EDIT-- Just tried it out... and it seems to work allright:
C# code
namespace Adder
{
public interface IAdder
{
double add(double a1, double a2);
}
public class Adder : IAdder
{
public Adder() { }
public double add(double a1, double a2) { return a1 + a2; }
}
}
Project settings
[assembly: ComVisible(true)]
[assembly: AssemblyDelaySign(false)]
(Signing was needed in order to be able to generate the tlb)
C++ code:
#import <adder.tlb> raw_interfaces_only
CoInitialize(NULL);
Adder::IAdderPtr a;
a.CreateInstance( __uuidof( Adder::Adder ) );
double d = 0;
a->add(1.,1., &d);
// note: the method will return a HRESULT;
// the output is stored in a reference variable.
CoUninitialize();
GetProcAddress does not understand C++ name mangling, not to mention any other mangling, so there is no dll for which "Class1::example_function1" could be valid identifier. Normally it's only used with extern "C" (or implemented in C without ++) functions, which are not mangled.
If it's implemented in VB.NET, it's not a dll at all. It's a .net assembly and you need to be running in CLR (.net runtime) to use it. You can run C++ code in CLR, but it has to be the "Managed C++", which is extended with special types for .net object references and operation with the garbage collector.
You can't directly access .NET code from native C++, you will need C++/CLI for that.
If your program needs to be native C++, there is the possibility of writing a mixed-mode wrapper DLL which provides a native C++ interface for the main program, and uses C++/CLI in the implementation to forward calls to the .NET DLL.
You would need to write a wrapper on C++/CLI for that . You might find the following link helpful. http://www.codeproject.com/KB/mcpp/cppcliintro01.aspx