100 lines
3.6 KiB
Diff
100 lines
3.6 KiB
Diff
Make optional variables work in a Windows DLL
|
||
Patch by Fedin Pavel
|
||
http://cygwin.com/ml/cygwin/2013-07/msg00337.html
|
||
|
||
diff -ru src/libargp-20110921.orig/gllib/argp.h src/libargp-20110921/gllib/argp.h
|
||
--- src/libargp-20110921.orig/gllib/argp.h 2011-09-23 03:31:26.000000000 +0500
|
||
+++ src/libargp-20110921/gllib/argp.h 2013-07-15 12:03:51.616647900 +0500
|
||
@@ -64,6 +64,18 @@
|
||
typedef int error_t;
|
||
# define __error_t_defined
|
||
#endif
|
||
+
|
||
+#ifndef DLL_EXPORT
|
||
+#ifdef __CYGWIN__
|
||
+#define __dllexport __declspec(dllexport)
|
||
+#endif
|
||
+#ifdef _WIN32
|
||
+#define __dllexport __declspec(dllexport)
|
||
+#endif
|
||
+#endif
|
||
+#ifndef __dllexport
|
||
+#define __dllexport
|
||
+#endif
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
@@ -441,14 +453,14 @@
|
||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||
will print this string followed by a newline and exit (unless the
|
||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||
-extern const char *argp_program_version;
|
||
+__dllexport extern const char *argp_program_version;
|
||
|
||
/* If defined or set by the user program to a non-zero value, then a default
|
||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||
calls this function with a stream to print the version to and a pointer to
|
||
the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
|
||
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
|
||
-extern void (*argp_program_version_hook) (FILE *__restrict __stream,
|
||
+__dllexport extern void (*argp_program_version_hook) (FILE *__restrict __stream,
|
||
struct argp_state *__restrict
|
||
__state);
|
||
|
||
@@ -457,12 +469,12 @@
|
||
argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
|
||
standard help messages), embedded in a sentence that says something like
|
||
`Report bugs to ADDR.'. */
|
||
-extern const char *argp_program_bug_address;
|
||
+__dllexport extern const char *argp_program_bug_address;
|
||
|
||
/* The exit status that argp will use when exiting due to a parsing error.
|
||
If not defined or set by the user program, this defaults to EX_USAGE from
|
||
<sysexits.h>. */
|
||
-extern error_t argp_err_exit_status;
|
||
+__dllexport extern error_t argp_err_exit_status;
|
||
|
||
/* Flags for argp_help. */
|
||
#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */
|
||
diff -ru src/libargp-20110921.orig/gllib/argp-parse.c src/libargp-20110921/gllib/argp-parse.c
|
||
--- src/libargp-20110921.orig/gllib/argp-parse.c 2011-09-23 03:31:26.000000000 +0500
|
||
+++ src/libargp-20110921/gllib/argp-parse.c 2013-07-15 11:39:49.690236100 +0500
|
||
@@ -64,6 +64,36 @@
|
||
/* EZ alias for ARGP_ERR_UNKNOWN. */
|
||
#define EBADKEY ARGP_ERR_UNKNOWN
|
||
|
||
+/* Windows does not support things like weak symbols, neither it will merge two
|
||
+ external symbols. In order to make our optional variables working, we have
|
||
+ to do this trick. What we do here is looking up respective variables in
|
||
+ main .exe file and patching our versions with correct pointers
|
||
+ Note that the whole thing relies on these variables being declared with
|
||
+ __declspec(dllexport). */
|
||
+#ifdef DLL_EXPORT
|
||
+
|
||
+#include <windows.h>
|
||
+
|
||
+#define PatchPtr(var) \
|
||
+ p = (void **)GetProcAddress(NULL, #var); \
|
||
+ if (p) var = *p;
|
||
+
|
||
+#define PatchInt(var) \
|
||
+ i = (int *)GetProcAddress(NULL, #var); \
|
||
+ if (i) var = *i;
|
||
+
|
||
+static void __attribute__((constructor)) patch_vars(void)
|
||
+{
|
||
+ void **p;
|
||
+ int *i;
|
||
+
|
||
+ PatchPtr(argp_program_version);
|
||
+ PatchPtr(argp_program_version_hook);
|
||
+ PatchPtr(argp_program_bug_address);
|
||
+ PatchInt(argp_err_exit_status);
|
||
+}
|
||
+#endif
|
||
+
|
||
/* Default options. */
|
||
|
||
/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
|
||
|