diff --git a/include/libirecovery.h b/include/libirecovery.h index ec9255b..5c3ad80 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h @@ -132,8 +132,6 @@ enum { /* library */ IRECV_API void irecv_set_debug_level(int level); IRECV_API const char* irecv_strerror(irecv_error_t error); -IRECV_API void irecv_init(void); /* deprecated: libirecovery has constructor now */ -IRECV_API void irecv_exit(void); /* deprecated: libirecovery has destructor now */ IRECV_API const char* irecv_version(); diff --git a/src/libirecovery.c b/src/libirecovery.c index 009ad76..fde15a9 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -71,6 +71,33 @@ #include "libirecovery.h" +// Reference: https://stackoverflow.com/a/2390626/1806760 +// Initializer/finalizer sample for MSVC and GCC/Clang. +// 2010-2016 Joe Lowe. Released into the public domain. + +#ifdef __cplusplus + #define INITIALIZER(f) \ + static void f(void); \ + struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \ + static void f(void) +#elif defined(_MSC_VER) + #pragma section(".CRT$XCU",read) + #define INITIALIZER2_(f,p) \ + static void f(void); \ + __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ + __pragma(comment(linker,"/include:" p #f "_")) \ + static void f(void) + #ifdef _WIN64 + #define INITIALIZER(f) INITIALIZER2_(f,"") + #else + #define INITIALIZER(f) INITIALIZER2_(f,"_") + #endif +#else + #define INITIALIZER(f) \ + static void f(void) __attribute__((__constructor__)); \ + static void f(void) +#endif + struct irecv_client_private { int debug; int usb_config; @@ -603,24 +630,6 @@ static libusb_context* irecv_hotplug_ctx = NULL; #endif #endif -static void _irecv_init(void) -{ - char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL"); - if (dbglvl) { - libirecovery_debug = strtol(dbglvl, NULL, 0); - irecv_set_debug_level(libirecovery_debug); - } -#ifndef USE_DUMMY -#ifndef _WIN32 -#ifndef HAVE_IOKIT - libusb_init(&libirecovery_context); -#endif -#endif - collection_init(&listeners); - mutex_init(&listener_mutex); -#endif -} - static void _irecv_deinit(void) { #ifndef USE_DUMMY @@ -637,43 +646,24 @@ static void _irecv_deinit(void) #endif } -static thread_once_t init_once = THREAD_ONCE_INIT; -static thread_once_t deinit_once = THREAD_ONCE_INIT; - -#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR - #if defined(__llvm__) || defined(__GNUC__) - #define HAVE_ATTRIBUTE_CONSTRUCTOR - #endif -#endif - -#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR -static void __attribute__((constructor)) libirecovery_initialize(void) +INITIALIZER(_irecv_init) { - thread_once(&init_once, _irecv_init); -} - -static void __attribute__((destructor)) libirecovery_deinitialize(void) -{ - thread_once(&deinit_once, _irecv_deinit); -} -#elif defined(_WIN32) -BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) -{ - switch (dwReason) { - case DLL_PROCESS_ATTACH: - thread_once(&init_once, _irecv_init); - break; - case DLL_PROCESS_DETACH: - thread_once(&deinit_once, _irecv_deinit); - break; - default: - break; + char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL"); + if (dbglvl) { + libirecovery_debug = strtol(dbglvl, NULL, 0); + irecv_set_debug_level(libirecovery_debug); } - return 1; -} -#else -#warning No compiler support for constructor/destructor attributes, some features might not be available. +#ifndef USE_DUMMY +#ifndef _WIN32 +#ifndef HAVE_IOKIT + libusb_init(&libirecovery_context); +#endif #endif + collection_init(&listeners); + mutex_init(&listener_mutex); +#endif + atexit(_irecv_deinit); +} #ifdef HAVE_IOKIT static int iokit_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) @@ -1334,20 +1324,6 @@ static int check_context(irecv_client_t client) } #endif -void irecv_init(void) -{ -#ifndef USE_DUMMY - thread_once(&init_once, _irecv_init); -#endif -} - -void irecv_exit(void) -{ -#ifndef USE_DUMMY - thread_once(&deinit_once, _irecv_deinit); -#endif -} - #ifndef USE_DUMMY #ifdef HAVE_IOKIT static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout)