Hey all. I'm having a problem with a DLL being loaded. In codeblocks, if I don't export Main + ALL the functions in my DLL, they cannot be used by an external program! Yet in visual studio, I exported nothing and external programs are able to load the DLL.

Example:

Main.cpp:

#include <windows.h>
#include "GLHook.hpp"

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            MessageBox(NULL, "", "", 0);
            DisableThreadLibraryCalls(hinstDLL);
            return Initialize();
        }
        break;

        case DLL_PROCESS_DETACH:
        {
            return DeInitialize();
        }
        break;
    }
    return TRUE;
}

GLHook.hpp:

typedef void (WINAPI *ptr_glAccum) (GLenum op, GLfloat value);

GLHook.cpp:

void GLHook_glAccum(GLenum op, GLfloat value)
{
    (*optr_glAccum) (op, value);
}


bool Initialize(void)
{
    if (!OriginalGL)
    {
        char Root[MAX_PATH];
        GetSystemDirectoryA(Root, MAX_PATH);
        strcat(Root, "\\opengl32.dll");

        OriginalGL = LoadLibraryA(Root);
        if (!OriginalGL) return false;

        if ((optr_glAccum = (ptr_glAccum) GetProcAddress(OriginalGL, "glAccum")) == NULL)
        {
            return false;
        }
}

.DEF File:

LIBRARY OpenGL32
;DESCRIPTION "GLHook Definition File"
EXPORTS

glAccum                    =    GLHook_glAccum;

Now the above will compile and work flawlessly in VisualStudio but in codeblocks it'll say "Cannot Export Symbols Undefined"..

When I do export it in codeblocks, it shows 700 symbols in the DLLExport Viewer whereas the Visual Studio one shows 350. The game Loads the Visual studio one but crashes immediately on the Codeblocks one. Visual studio is 80kb in size whereas codeblocks is 744kb.

Why does it do this in codeblocks? I want to use Codeblocks so I can use C++11 ={ Anyway to fix it?

In other words, DLLExport view is showing:

glAccum; //Original functions and..
GLHook_glAccum @8; //The detoured functions.

for codeblocks whereas visual studio one just shows:
glAccum;

Edited 4 Years Ago by triumphost

First things to verify:

  • Are all your exported functions marked as having __stdcall as a calling convention?
  • Are all your exported functions (or your whole code) marked with extern "C"?

If both answers are not "yes", then fix that before trying anything else.

Now the above will compile and work flawlessly in VisualStudio but in codeblocks it'll say "Cannot Export Symbols Undefined"..

If it cannot find the symbols to be exported, then that's a problem. First of all, you shouldn't need a def file at all when using MinGW/GCC (the compiler used by Code-Blocks), because GCC exports all global functions that are not marked as static (or don't fall in one of the "no linkage" or "internal linkage" cases). Long story short, everything is exported by default in GCC DLLs.

Second, it is usually easier to write a .def file by first generating it from the DLL or object files. MinGW has a tool for that, it is called "dlltool". You can then use the def file to rename or re-ordinate the symbols when remaking the dll. If you start from that, you should have no more issue of "Cannot Export Symbols Undefined.".

When I do export it in codeblocks, it shows 700 symbols in the DLLExport Viewer whereas the Visual Studio one shows 350.

That is because there are 350 symbols that you specified in the .def file and 350 symbols that are the automatically exported functions. While the MSVC version only has the exported symbols you specified in the def file.

The game Loads the Visual studio one but crashes immediately on the Codeblocks one.

That is probably because it hooks to the def-specified symbols, which didn't get resolve correctly (i.e., the error you got earlier with undefined symbols). Or, it is because you didn't specify the __stdcall calling convention on the functions.

Visual studio is 80kb in size whereas codeblocks is 744kb.

This is because MSVC will link all the "standard" functions (the C/C++ standard functions and the windows functions) dynamically, i.e., in CRT libraries (C Run-Time libraries). On the other hand, MinGW/GCC links to them statically (at least, by default), which leads to a size overhead as all this standard code is basically incorporated into your DLL.

Why does it do this in codeblocks? I want to use Codeblocks so I can use C++11 ={ Anyway to fix it?

If you want to use C++11, make sure you have the bleeding edge version of MinGW/GCC. Now, it should be 4.7.0 or above.

In other words, DLLExport view is showing:

glAccum; //Original functions and..
GLHook_glAccum @8; //The detoured functions.

As I said, you have the def-specified symbol and the automatically exported function (with original name). For that name decoration, it seems that your functions are correctly specified with __stdcall and extern "C". That decorated name (GLHook_glAccum@8) is most probably the one you need to use on the right-hand-side of the "=" sign in your def file.

Ahh that solved it with the extern "C" and __stdcall.

Only problem now is that it says:
Warning: resolving _GLHook_glAccum by linking to _GLHook_glAccum@8

I have to use the def file because if I don't use it, how will the original function point to mine?

Example:

glAccum = GLHook_Accum;

Doesn't that redirect all calls to glAccum to GLHook_Accum? That's what I read on MSDN:

For example, if your DLL exports a function, func1() and you want it to be used as func2(), you would specify:

EXPORTS
func2=func1

http://msdn.microsoft.com/en-us/library/hyx1zcd3%28v=vs.80%29.aspx

When I don't use the DEF file, the warnings are gone.. But then again, it doesn't work unless I use it. I'll try the dlltool. :) Thank you.

Only problem now is that it says:
Warning: resolving _GLHook_glAccum by linking to _GLHook_glAccum@8

This is only due to the fact that GCC (and other compilers) will generally disregard name-decoration (which is the @8 thing at the end of the name) when matching the symbols. So, it matches the symbol _GLHook_glAccum to the decorated symbol _GLHook_glAccum@8, but it warns you about it because it could be a mistake on your part. With decoration usually signifies that it is __stdcall, without the decoration it usually means it is __cdecl, which are different calling conventions. But these are not super strict rules (it's an old ad-hoc Microsoft rule (how surprising... (sarcasms))), so the compiler only generates a warning about it. To quell the warning you should have the decoration in your def-file symbols (right-hand-side of the equal sign).

I have to use the def file because if I don't use it, how will the original function point to mine?

Yes, renaming the functions to be exported is a valid reason for using a def-file. You could get the same effect otherwise (e.g., making wrapper functions (either in the cpp or header), or using the exported function names directly, i.e., without the GLHook_ prefix), but these are not nice solutions or even appropriate at all. But, renaming the functions in a DLL is not a very common thing that people do, that's why I said that "normally you don't need the def-file". In your case, it makes sense.

Doesn't that redirect all calls to glAccum to GLHook_Accum?

Yes it does redirect all calls to glAccum to GLHook_Accum.

I'll try the dlltool. :)

My advice is to use dlltool to generate a vanilla def-file from the DLL compiled without a def-file. It should be a pretty straight forward def-file. Then, write a simple program or script that does a kind of search-and-replace on the def-file to automatically generate the exported names, like the glAccum from your example. For instance, you detect the pattern GLHook_gl*@* and replace it with gl* = GLHook_gl*@* on every line of the def-file. That's just to avoid you the painful task of manually entering 350 function names.

Edited 4 Years Ago by mike_2000_17: typos

Comments
Good Info. I needed that.

Oohhh I see what you mean. Yeah lol I never actually wrote all 350+ in the def file at all.

I used a library I've been working on ever since I started C++ and I made a little script. It'll take the typedefs and generate all the externs, def file functions, detours and address functions =]

Thanks for the advice and input =] I got it all solved now :D

Edited 4 Years Ago by triumphost

This question has already been answered. Start a new discussion instead.