2013-06-02 11 views
15

Ok, więc mam około 500 wskaźników funkcji zdefiniowanych w nagłówku tak jak na przykład:99% CPU, 3.51MB bez typedef

void (__stdcall *ptr_glAccum) (GLenum op, GLfloat value); 
void (__stdcall *ptr_glActiveTextureARB) (GLenum texture); 
void (__stdcall *ptr_glAlphaFunc) (GLenum func, GLclampf ref); 
GLboolean (__stdcall *ptr_glAreTexturesResident) (GLsizei n, const GLuint *textures, GLboolean *residences); 
void (__stdcall *ptr_glArrayElement) (GLint index); 
void (__stdcall *ptr_glBegin) (GLenum mode); 
void (__stdcall *ptr_glBindBufferARB) (GLenum target, GLuint buffer); 
void (__stdcall *ptr_glBindTexture) (GLenum target, GLuint texture); 
void (__stdcall *ptr_glBitmap) (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); 
void (__stdcall *ptr_glBlendFunc) (GLenum sfactor, GLenum dfactor); 
void (__stdcall *ptr_glBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); 

itp .. Teraz powód I nie umieścić typedef lub nie chcieć, ponieważ mogę przypisać i użyć wskaźników powyżej bezpośrednio. Jednak jeśli używam typedef, to potrzebuję utworzyć zmienną tego typu i przypisać do niego, a następnie użyć go. To podwaja mój kod z 500 linii do 1000+.

Teraz, gdy dodaję typedef na początku każdego z tych wskaźników funkcji, moja biblioteka dll ma rozmiar 300kb i kompiluje się w mniej niż 5 sekund. Jednak jeśli usuniemy typedef, jak pokazano powyżej, przeskakuje ona do 99% procesora podczas kompilowania i wyprowadzania pliku dll 3.51 MB podczas kompilacji trwającego 3-4 minuty. To oburzające, że jedno słowo kluczowe powoduje tyle kłopotów.

ciągu pliku def DLL, to pokazuje:

ptr_wglUseFontBitmapsA @940 DATA 
ptr_wglUseFontBitmapsW @941 DATA 
ptr_wglUseFontOutlinesA @942 DATA 
ptr_wglUseFontOutlinesW @943 DATA 

Ale z typedef, że "dane" część nie ma.

Wszelkie pomysły, dzięki którym typedef jest tak wyjątkowy i dlaczego to zachowanie bez niego: S? Używam MinGW g ++ 4.7.2 z CodeBlocks Windows 7 x64 3.7Ghz I7 8 Gb Ram z istoty wyjściowego kompilator:

-------------- Clean: Release in OpenGL32 (compiler: GNU GCC Compiler)--------------- 

Cleaned "OpenGL32 - Release" 

-------------- Build: Release in OpenGL32 (compiler: GNU GCC Compiler)--------------- 

x86_64-w64-mingw32-g++.exe -O2 -std=c++11 -Wall -DBUILD_DLL -std=c++11 -c C:\Users\Brandon\Desktop\OpenGL32\Implementations\Exports.cpp -o obj\Release\Implementations\Exports.o 
x86_64-w64-mingw32-g++.exe -O2 -std=c++11 -Wall -DBUILD_DLL -std=c++11 -c C:\Users\Brandon\Desktop\OpenGL32\main.cpp -o obj\Release\main.o 
x86_64-w64-mingw32-g++.exe -shared -Wl,--output-def=bin\Release\libOpenGL32.def -Wl,--out-implib=bin\Release\libOpenGL32.a -Wl,--dll obj\Release\Implementations\Exports.o obj\Release\main.o -o bin\Release\OpenGL32.dll -s -static -static-libgcc -static-libstdc++ -luser32 -lgdi32 -lopengl32 -lglu32 
Output size is 3.51 MB 
Process terminated with status 0 (2 minutes, 39 seconds) 
0 errors, 0 warnings (2 minutes, 39 seconds) 

EDIT: Cały DLL (zawierający tylko 1/500 wskazówek func na żądanie):

Exports.hpp:

#ifndef EXPORTS_HPP_INCLUDED 
#define EXPORTS_HPP_INCLUDED 

#include <GL/gl.h> 
#include <GL/glext.h> 
#include "Platform.hpp" 


extern Library* OriginalGL; 

void (__stdcall *ptr_glAccum) (GLenum op, GLfloat value); 

#endif // EXPORTS_HPP_INCLUDED 

Exports.cpp:

#include "Exports.hpp" 

Library* OriginalGL = nullptr; 

bool __stdcall Initialized(void) 
{ 
    char Root[MAX_PATH]; 
    #if defined _WIN32 || defined _WIN64 
     GetSystemDirectoryA(Root, MAX_PATH); 
    #ifdef _MSC_VER 
     strcat_s(Root, "\\opengl32.dll"); 
    #else 
     strcat(Root, "\\opengl32.dll"); 
    #endif 
    #else 
     strcat(Root, "/usr/lib"); 
     strcat(Root, "/libGL.so"); 
    #endif 

    OriginalGL = new Library(Root); 
    return OriginalGL->FunctionAddress(ptr_glAccum, "glAccum"); //Just a thin class wrapper around GetProcAddress and LoadLibrary. 
} 

bool __stdcall DeInitialize(void) 
{ 
    if (OriginalGL) 
    { 
     delete OriginalGL; 
     OriginalGL = nullptr; 
     return true; 
    } 
    return false; 
} 

extern "C" __stdcall void DetourHook_glAccum(GLenum op, GLfloat value) 
{ 
    (*ptr_glAccum) (op, value); 
} 

main.cpp:

#include <windows.h> 

extern "C" bool __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
{ 
    switch (fdwReason) 
    { 
     case DLL_PROCESS_ATTACH: 
      break; 

     case DLL_PROCESS_DETACH: 
      break; 

     default: 
      break; 
    } 
    return true; 
} 
+1

Czy jest to specyficzne dla określonego kompilatora? Pomocne może być określenie używanego kompilatora, a także jego wersji. – misha

+0

Co masz na myśli mówiąc "dodaj typedef na początku"? Czy możesz pokazać jakiś przykład tego? –

+0

Używam g ++ Mingw z Codeblocks IDE na Windows x64 3.7Ghz I7 8GB pamięci RAM. : S Mam na myśli to: 'typedef void (__stdcall * ptr_glAccum) (GLenum op, GLfloat value);' – Brandon

Odpowiedz

17

Z typedef Twój nagłówek produkuje wiele nowych typów, każdy rodzaj wskaźnik funkcji. Typy są przydatne tylko w procesie kompilacji i nie powodują żadnych śladów w samej bibliotece DLL. typedef ma nie utworzyć żadnych zmiennych globalnych.

Jednak bez nagłówka typedef tworzona jest seria zmiennych globalnych, z których każda jest wskaźnikiem funkcji. Zmienne globalne pobierają wpis w bibliotece DLL, zwiększając czas produkcji pliku i jego ostateczny rozmiar.

+0

Tak, ale nadal muszę utworzyć te zmienne globalne za pomocą typedef, więc co to za różnica: S Zobacz zaktualizowaną próbkę OP z typedef? – Brandon

+0

Myślę, że przyjmuję twoją odpowiedź, chyba że ktoś inny ma lepszy pomysł, ale wciąż nie widzę różnicy między używaniem typedef i deklarowaniem kiści globali a używaniem wskaźnika funkcji bezpośrednio. Wiki nie mówi nic poza zwykłym pseudonimem. – Brandon

+0

Dodano linię do mojej odpowiedzi. 'typedef' robi * nie * produkuje zmienne globalne! Najprawdopodobniej chcesz mieć tutaj zmienne globalne, a nie typy. – CygnusX1