Skip to content

Instantly share code, notes, and snippets.

@steeve
Created October 6, 2013 21:42
Show Gist options
  • Save steeve/6859467 to your computer and use it in GitHub Desktop.
Save steeve/6859467 to your computer and use it in GitHub Desktop.
diff -rupN swig-2.0.11/Doc/Manual/Go.html swig-2.0.11.tmp/Doc/Manual/Go.html
--- swig-2.0.11/Doc/Manual/Go.html 2013-09-15 23:06:10 +0200
+++ swig-2.0.11.tmp/Doc/Manual/Go.html 2013-09-25 09:42:11 +0200
@@ -139,6 +139,10 @@ swig -go -help
or <tt>int64</tt>. The &lt;s&gt; argument should be 32 or 64.</td>
</tr>
+<tr>
+<td>-windows</td>
+<td>Generate code for Windows.</td>
+</tr>
</table>
<H3><a name="Go_outputs"></a>22.2.2 Go Output Files</H3>
@@ -157,6 +161,8 @@ compiler.
MODULE_wrap.c or MODULE_wrap.cxx will contain C/C++ functions will be
invoked by the Go wrapper code. This file should be compiled with the
usual C or C++ compiler and linked into a shared library.
+If generate code for Windows, MODULE_dllmain.cxx will contain C++ code
+for dll init.
<li>
MODULE_wrap.h will be generated if you use the directors feature. It
provides a definition of the generated C++ director classes. It is
@@ -186,6 +192,23 @@ A typical command sequence would look li
% 6l main.6
</pre></div>
+<p>
+For Windows, this would look like this:
+</p>
+
+<div class="code"><pre>
+% swig -go -c++ -windows example.i
+% g++ -c example.cxx
+% g++ -c example_wrap.cxx
+% g++ -c example_dllmain.cxx
+% g++ -shared example.o example_wrap.o example_dllmain.o -o example.dll
+% 8g example.go
+% 8c -I ${GOROOT}/pkg/${GOOS}_${GOARCH} example_gc.c
+% gopack grc example.a example.8 example_gc.8
+% 8g main.go # your code, not generated by SWIG
+% 8l main.8
+</pre></div>
+
<H2><a name="Go_basic_tour"></a>22.3 A tour of basic C/C++ wrapping</H2>
diff -rupN swig-2.0.11/Examples/go/callback/Makefile.win swig-2.0.11.tmp/Examples/go/callback/Makefile.win
--- swig-2.0.11/Examples/go/callback/Makefile.win 1970-01-01 01:00:00 +0100
+++ swig-2.0.11.tmp/Examples/go/callback/Makefile.win 2013-09-25 09:33:42 +0200
@@ -0,0 +1,24 @@
+TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+CXXSRCS = example.cxx
+TARGET = example
+INTERFACE = example.i
+SWIGOPT = -windows
+
+all:: go
+
+go::
+ ../../../preinst-swig -go -c++ ${SWIGOPT} ${INTERFACE}
+ 8g example.go
+ g++ -g -c example.cxx example_wrap.cxx example_dllmain.cxx
+ g++ -shared example.o example_wrap.o example_dllmain.o -o example.dll -Wl,--out-imp,libexample.a
+ 8c -I ${GOROOT}/pkg/${GOOS}_${GOARCH} example_gc.c
+ gopack grc example.a example.8 example_gc.8
+ 8g runme.go
+ 8l -o runme.exe runme.8
+
+clean::
+ $(MAKE) -f $(TOP)/Makefile go_clean
+
+check: all
+ $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run
diff -rupN swig-2.0.11/Lib/go/goruntime.swg swig-2.0.11.tmp/Lib/go/goruntime.swg
--- swig-2.0.11/Lib/go/goruntime.swg 2013-09-15 16:11:43 +0200
+++ swig-2.0.11.tmp/Lib/go/goruntime.swg 2013-09-25 09:33:42 +0200
@@ -53,34 +53,6 @@ swiggo_size_assert(swiggo_long_long, 8)
swiggo_size_assert(float, 4)
swiggo_size_assert(double, 8)
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern void crosscall2(void (*fn)(void *, int), void *, int);
-extern void _cgo_allocate(void *, int);
-extern void _cgo_panic(void *, int);
-#ifdef __cplusplus
-}
-#endif
-
-static void *_swig_goallocate(size_t len) {
- struct {
- size_t len;
- void *ret;
- } a;
- a.len = len;
- crosscall2(_cgo_allocate, &a, (int) sizeof a);
- return a.ret;
-}
-
-static void _swig_gopanic(const char *p) {
- struct {
- const char *p;
- } a;
- a.p = p;
- crosscall2(_cgo_panic, &a, (int) sizeof a);
-}
-
%}
/* Boilerplate for C code when using 6g/8g. This code is compiled
@@ -169,6 +141,54 @@ void SwigCgocallBackDone() {
#endif
+#ifdef SWIGGO_WINDOWS
+%insert(runtime) %{
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void (*crosscall2)(void (*fn)(void *, int), void *, int);
+extern void (*_cgo_allocate)(void *, int);
+extern void (*_cgo_panic)(void *, int);
+#ifdef __cplusplus
+}
+#endif
+%}
+#else
+%insert(runtime) %{
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void crosscall2(void (*fn)(void *, int), void *, int);
+extern void _cgo_allocate(void *, int);
+extern void _cgo_panic(void *, int);
+#ifdef __cplusplus
+}
+#endif
+%}
+#endif
+
+#ifndef SWIGGO_GCCGO
+%insert(runtime) %{
+static void *_swig_goallocate(size_t len) {
+ struct {
+ size_t len;
+ void *ret;
+ } a;
+ a.len = len;
+ crosscall2(_cgo_allocate, &a, (int) sizeof a);
+ return a.ret;
+}
+
+static void _swig_gopanic(const char *p) {
+ struct {
+ const char *p;
+ } a;
+ a.p = p;
+ crosscall2(_cgo_panic, &a, (int) sizeof a);
+}
+%}
+#endif
+
%insert(runtime) %{
static _gostring_ _swig_makegostring(const char *p, size_t l) {
@@ -216,3 +236,54 @@ type _ unsafe.Pointer
type _swig_fnptr *byte
type _swig_memberptr *byte
%}
+
+#ifndef SWIGGO_GCCGO
+
+%insert(dllmain) %{
+#include <windows.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void (*crosscall2)(void (*fn)(void *, int), void *, int);
+void (*_cgo_allocate)(void *, int);
+void (*_cgo_panic)(void *, int);
+#ifdef __cplusplus
+}
+#endif
+
+static void initdynexports(HMODULE h);
+
+extern "C" BOOL WINAPI
+DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ HMODULE hModule;
+ hModule = GetModuleHandle(NULL);
+ crosscall2 = (void (*)(void (*fn)(void *, int), void *, int))GetProcAddress(hModule, "crosscall2");
+ assert(crosscall2 != NULL);
+ _cgo_allocate = (void (*)(void *, int))GetProcAddress(hModule, "_cgo_allocate");
+ assert(_cgo_allocate != NULL);
+ _cgo_panic = (void (*)(void *, int))GetProcAddress(hModule, "_cgo_panic");
+ assert(_cgo_panic != NULL);
+
+ initdynexports(hModule);
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return TRUE;
+}
+%}
+#endif
\ No newline at end of file
diff -rupN swig-2.0.11/Source/Modules/go.cxx swig-2.0.11.tmp/Source/Modules/go.cxx
--- swig-2.0.11/Source/Modules/go.cxx 2013-09-15 16:11:43 +0200
+++ swig-2.0.11.tmp/Source/Modules/go.cxx 2013-09-25 09:43:18 +0200
@@ -28,6 +28,8 @@ class GO:public Language {
int long_type_size;
// Size in bits of the Go type "int". 0 if not specified.
int intgo_type_size;
+ // Flag for Windows
+ bool is_windows;
/* Output files */
File *f_c_begin;
@@ -47,6 +49,7 @@ class GO:public Language {
File *f_gc_runtime;
File *f_gc_header;
File *f_gc_wrappers;
+ File *f_dllmain;
// True if we imported a module.
bool saw_import;
@@ -80,6 +83,8 @@ class GO:public Language {
// A hash table of classes which were defined. The index is a Go
// type name.
Hash *defined_types;
+ // A hash table of dynexport.
+ Hash *dynexports;
public:
GO():package(NULL),
@@ -88,6 +93,7 @@ public:
go_prefix(NULL),
soname(NULL),
long_type_size(32),
+ is_windows(false),
intgo_type_size(0),
f_c_begin(NULL),
f_go_begin(NULL),
@@ -104,6 +110,7 @@ public:
f_gc_runtime(NULL),
f_gc_header(NULL),
f_gc_wrappers(NULL),
+ f_dllmain(NULL),
saw_import(false),
imported_package(NULL),
interfaces(NULL),
@@ -114,7 +121,8 @@ public:
making_variable_wrappers(false),
is_static_member_function(false),
undefined_types(NULL),
- defined_types(NULL) {
+ defined_types(NULL),
+ dynexports(NULL) {
director_multiple_inheritance = 1;
director_language = 1;
director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
@@ -144,6 +152,9 @@ private:
} else if (strcmp(argv[i], "-gccgo") == 0) {
Swig_mark_arg(i);
gccgo_flag = true;
+ } else if (strcmp(argv[i], "-windows") == 0) {
+ Swig_mark_arg(i);
+ is_windows = true;
} else if (strcmp(argv[i], "-go-prefix") == 0) {
if (argv[i + 1]) {
go_prefix = NewString(argv[i + 1]);
@@ -198,6 +209,10 @@ private:
if (gccgo_flag && !go_prefix) {
go_prefix = NewString("go");
}
+
+ if (is_windows) {
+ Preprocessor_define("SWIGGO_WINDOWS 1", 0);
+ }
// Add preprocessor symbol to parser.
Preprocessor_define("SWIGGO 1", 0);
@@ -276,7 +291,10 @@ private:
}
if (!soname) {
soname = Copy(package);
- Append(soname, ".so");
+ if (is_windows)
+ Append(soname, ".dll");
+ else
+ Append(soname, ".so");
}
// Get filenames.
@@ -292,7 +310,10 @@ private:
gc_filename = NewString("");
Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module);
}
-
+
+ String *gc_dllmain_filename = NewString("");
+ Printf(gc_dllmain_filename, "%s%s_dllmain.cxx", SWIG_output_directory(), module);
+
// Open files.
f_c_begin = NewFile(c_filename, "w", SWIG_output_files());
@@ -318,6 +339,14 @@ private:
FileErrorDisplay(go_filename);
SWIG_exit(EXIT_FAILURE);
}
+
+ if (is_windows) {
+ f_dllmain = NewFile(gc_dllmain_filename, "w", SWIG_output_files());
+ if (!f_dllmain) {
+ FileErrorDisplay(gc_dllmain_filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
if (!gccgo_flag) {
f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
@@ -352,6 +381,7 @@ private:
Swig_register_filebyname("go_runtime", f_go_runtime);
Swig_register_filebyname("go_header", f_go_header);
Swig_register_filebyname("go_wrapper", f_go_wrappers);
+ Swig_register_filebyname("dllmain", f_dllmain);
if (!gccgo_flag) {
Swig_register_filebyname("gc_begin", f_gc_begin);
Swig_register_filebyname("gc_runtime", f_gc_runtime);
@@ -381,7 +411,8 @@ private:
if (!gccgo_flag) {
Swig_banner(f_gc_begin);
Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
- Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
+ if (!is_windows)
+ Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
}
// Output module initialization code.
@@ -405,6 +436,7 @@ private:
undefined_types = NewHash();
defined_types = NewHash();
+ dynexports = NewHash();
// Emit code.
@@ -432,6 +464,18 @@ private:
}
Delete(undefined_types);
Delete(defined_types);
+
+ for (Iterator p = First(dynexports); p.key; p = Next(p)) {
+ String *name = p.key;
+ Printv(f_dllmain, "void (*", name, ")(void *, int);\n", NULL);
+ }
+ Printv(f_dllmain, "static void initdynexports(HMODULE h) {", "\n", NULL);
+ for (Iterator p = First(dynexports); p.key; p = Next(p)) {
+ String *name = p.key;
+ Printf(f_dllmain, "%s = (void (*)(void*, int))GetProcAddress(h, \"%s\");\n", name, name);
+ }
+ Printv(f_dllmain, "}\n", NULL);
+ Delete(dynexports);
/* Write and cleanup */
@@ -480,6 +524,8 @@ private:
if (!gccgo_flag) {
Delete(f_gc_begin);
}
+
+ Delete(f_dllmain);
return SWIG_OK;
}
@@ -1073,9 +1119,13 @@ private:
int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) {
Wrapper *f = NewWrapper();
- Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
+ if (is_windows)
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"", soname, "\"\n", NULL);
+ else
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL);
- Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
+ if (!is_windows)
+ Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
Printv(f->def, "\n", NULL);
Printv(f->def, "void\n", NULL);
@@ -1131,7 +1181,10 @@ private:
Delete(parm_size);
Printv(f->code, "{\n", NULL);
- Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
+ if (is_windows)
+ Printv(f->code, "\truntime\xc2\xb7" "cgocall(", wname, ", &p);\n", NULL);
+ else
+ Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
Printv(f->code, "}\n", NULL);
Printv(f->code, "\n", NULL);
@@ -2792,7 +2845,10 @@ private:
if (!is_ignored) {
if (!gccgo_flag) {
- Printv(f_c_directors, "extern \"C\" void ", wname, "(void*, int);\n", NULL);
+ if (is_windows)
+ Printv(f_c_directors, "extern \"C\" void (*", wname, ")(void*, int);\n", NULL);
+ else
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(void*, int);\n", NULL);
} else {
Printv(f_c_directors, "extern \"C\" void ", wname, "(void*) __asm__(\"", go_prefix, ".", package, ".", go_name, "\");\n", NULL);
}
@@ -2814,6 +2870,10 @@ private:
Printv(f_c_directors, " a.p = go_val;\n", NULL);
Printv(f_c_directors, " crosscall2(", wname, ", &a, (int) sizeof a);\n", NULL);
+ if (is_windows) {
+ Setattr(dynexports, wname, wname);
+ }
+
Printv(f_gc_wrappers, "#pragma dynexport ", wname, " ", wname, "\n", NULL);
Printv(f_gc_wrappers, "extern void \xc2\xb7", go_name, "();\n", NULL);
Printv(f_gc_wrappers, "void\n", NULL);
@@ -3393,7 +3453,10 @@ private:
Delete(upcall_wname);
if (!gccgo_flag) {
- Printv(f_c_directors, "extern \"C\" void ", callback_wname, "(void*, int);\n", NULL);
+ if (is_windows)
+ Printv(f_c_directors, "extern \"C\" void (*", callback_wname, ")(void*, int);\n", NULL);
+ else
+ Printv(f_c_directors, "extern \"C\" void ", callback_wname, "(void*, int);\n", NULL);
} else {
Printv(f_c_directors, "extern \"C\" ", NULL);
@@ -3532,7 +3595,11 @@ private:
Delete(result_str);
}
- // The C wrapper code which calls the Go function.
+ if (is_windows) {
+ Setattr(dynexports, callback_wname, callback_wname);
+ }
+
+ // The C wrapper code which calls the Go function.
Printv(f_gc_wrappers, "#pragma dynexport ", callback_wname, " ", callback_wname, "\n", NULL);
Printv(f_gc_wrappers, "extern void \xc2\xb7", callback_name, "();\n", NULL);
Printv(f_gc_wrappers, "void\n", NULL);
@@ -4900,4 +4967,5 @@ Go Options (available with -go)\n\
-intgosize <s> - Set size of Go int type--32 or 64 bits\n\
-package <name> - Set name of the Go package to <name>\n\
-soname <name> - Set shared library holding C/C++ code to <name>\n\
+ -windows - Generate code for Windows\n\
\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment