swig go support windows port

532 views
Skip to first unread message

Wei guangjing

unread,
Feb 12, 2011, 10:46:58 PM2/12/11
to golang-nuts
Hi,

I just make a patch for swig go support windows port, swig go really useful for bind c++ to go, please see the attachments for patch.
I add -windows and -exename to args for windows dynimport and dynexport, for example, Example/go/callback make process as follow:
../../../preinst-swig -go -c++  -windows -exename runme.exe example.i
8g -I . example.go
dlltool -d runme.exe.def -l runme.a
g++ -g -c    example.cxx example_wrap.cxx
g++ -shared    example.o example_wrap.o runme.a  -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 -I . runme.go
8l -o runme.exe -L . runme.8
./runme.exe

--
Wei guangjing
swig_go_windows.patch

Andrew Gerrand

unread,
Feb 13, 2011, 4:59:53 PM2/13/11
to Wei guangjing, golang-nuts
Nice work!

Is it practical to send these changes upstream to SWIG?

Ian Lance Taylor

unread,
Feb 13, 2011, 11:23:55 PM2/13/11
to Wei guangjing, golang-nuts
Wei guangjing <vcc...@gmail.com> writes:

> I just make a patch for swig go support windows port, swig go really useful
> for bind c++ to go, please see the attachments for patch.

Thanks! Can you also provide a patch which updates the documentation in
Doc/Manual/Go.html?

It would also be helpful to e-mail the patch to
swig-...@lists.sourceforge.net to see what the SWIG developers think
of it.

Thanks.

Ian

> I add -windows and -exename to args for windows dynimport and dynexport, for
> example, Example/go/callback make process as follow:
> ../../../preinst-swig -go -c++ -windows -exename runme.exe example.i
> 8g -I . example.go
> dlltool -d runme.exe.def -l runme.a
> g++ -g -c example.cxx example_wrap.cxx
> g++ -shared example.o example_wrap.o runme.a -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 -I . runme.go
> 8l -o runme.exe -L . runme.8
> ./runme.exe
>
> --
> Wei guangjing
>

> Index: Examples/go/callback/Makefile.win
> ===================================================================
> --- Examples/go/callback/Makefile.win (revision 0)
> +++ Examples/go/callback/Makefile.win (revision 0)
> @@ -0,0 +1,26 @@
> +TOP = ../..
> +SWIG = $(TOP)/../preinst-swig
> +CXXSRCS = example.cxx
> +TARGET = example
> +INTERFACE = example.i
> +SWIGOPT = -windows -exename runme.exe
> +LIBS=-L. -lrunme
> +
> +all:: go
> +
> +go::
> + ../../../preinst-swig -go -c++ ${SWIGOPT} ${INTERFACE}
> + 8g -I . example.go
> + dlltool -d runme.exe.def -l runme.a
> + g++ -g -c example.cxx example_wrap.cxx
> + g++ -shared example.o example_wrap.o runme.a -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 -I . runme.go
> + 8l -o runme.exe -L . runme.8
> +
> +clean::
> + $(MAKE) -f $(TOP)/Makefile go_clean
> +
> +check: all
> + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run
> Index: Source/Modules/go.cxx
> ===================================================================
> --- Source/Modules/go.cxx (revision 12454)
> +++ Source/Modules/go.cxx (working copy)
> @@ -27,6 +27,9 @@
> String *soname;
> // Size in bits of the C type "long".
> int long_type_size;
> + // Flag for Windows
> + bool windows_flag;
> + String *exename;
>
> /* Output files */
> File *f_c_begin;
> @@ -46,6 +49,7 @@
> File *f_gc_runtime;
> File *f_gc_header;
> File *f_gc_wrappers;
> + File *f_gc_dynexports;
>
> // True if we imported a module.
> bool saw_import;
> @@ -86,6 +90,8 @@
> go_prefix(NULL),
> soname(NULL),
> long_type_size(32),
> + windows_flag(false),
> + exename(NULL),
> f_c_begin(NULL),
> f_go_begin(NULL),
> f_gc_begin(NULL),
> @@ -101,6 +107,7 @@
> f_gc_runtime(NULL),
> f_gc_header(NULL),
> f_gc_wrappers(NULL),
> + f_gc_dynexports(NULL),
> saw_import(false),
> imported_package(NULL),
> interfaces(NULL),
> @@ -138,6 +145,9 @@
> } 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);
> + windows_flag = true;
> } else if (strcmp(argv[i], "-go-prefix") == 0) {
> if (argv[i + 1]) {
> go_prefix = NewString(argv[i + 1]);
> @@ -156,6 +166,15 @@
> } else {
> Swig_arg_error();
> }
> + } else if (strcmp(argv[i], "-exename") == 0) {
> + if (argv[i + 1]) {
> + exename = NewString(argv[i + 1]);
> + Swig_mark_arg(i);
> + Swig_mark_arg(i + 1);
> + i++;
> + } else {
> + Swig_arg_error();
> + }
> } else if (strcmp(argv[i], "-longsize") == 0) {
> if (argv[i + 1]) {
> long_type_size = atoi(argv[i + 1]);
> @@ -240,7 +259,10 @@
> }
> if (!soname) {
> soname = Copy(package);
> - Append(soname, ".so");
> + if (windows_flag)
> + Append(soname, ".dll");
> + else
> + Append(soname, ".so");
> }
>
> // Get filenames.
> @@ -256,6 +278,12 @@
> gc_filename = NewString("");
> Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module);
> }
> +
> + String *gc_dynexport_filename = NULL;
> + if (windows_flag && exename) {
> + gc_dynexport_filename = NewString("");
> + Printf(gc_dynexport_filename, "%s.def", exename);
> + }
>
> // Open files.
>
> @@ -282,6 +310,14 @@
> FileErrorDisplay(go_filename);
> SWIG_exit(EXIT_FAILURE);
> }
> +
> + if (windows_flag && exename) {
> + f_gc_dynexports = NewFile(gc_dynexport_filename, "w", SWIG_output_files());
> + if (!f_gc_dynexports) {
> + FileErrorDisplay(gc_dynexport_filename);
> + SWIG_exit(EXIT_FAILURE);
> + }
> + }
>
> if (!gccgo_flag) {
> f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
> @@ -341,9 +377,16 @@
> 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 (!windows_flag)
> + Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
> }
>
> + if (windows_flag && exename) {
> + Printf(f_gc_dynexports, "LIBRARY %s\n", exename);
> + Printf(f_gc_dynexports, "EXPORTS\n");
> + Printf(f_gc_dynexports, "_cgo_allocate\n_cgo_panic\ncrosscall2\n");
> + }
> +
> // Output module initialization code.
>
> Printf(f_go_begin, "\npackage %s\n\n", package);
> @@ -998,9 +1041,13 @@
> 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 (windows_flag)
> + 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 (!windows_flag)
> + Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
> Printv(f->def, "\n", NULL);
> Printv(f->def, "void\n", NULL);
>
> @@ -1056,7 +1103,10 @@
> Delete(parm_size);
>
> Printv(f->code, "{\n", NULL);
> - Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
> + if (windows_flag)
> + 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);
>
> @@ -2737,6 +2787,8 @@
> Printv(f_c_directors, " a.p = go_val;\n", NULL);
> Printv(f_c_directors, " crosscall2(", wname, ", &a, (int) sizeof a);\n", NULL);
>
> + if (windows_flag && exename)
> + Printf(f_gc_dynexports, "%s\n", 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);
> @@ -3463,6 +3515,8 @@
> }
>
> // The C wrapper code which calls the Go function.
> + if (windows_flag && exename)
> + Printf(f_gc_dynexports, "%s\n", callback_wname);
> 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);
> @@ -4743,4 +4797,6 @@
> -go-prefix <p> - Like gccgo -fgo-prefix option\n\
> -soname <name> - Set shared library holding C/C++ code to <name>\n\
> -longsize <s> - Set size of C/C++ long type--32 or 64 bits\n\
> + -windows - Windows\n\
> + -exename - exe file name, for Windows\n\
> \n";

Wei guangjing

unread,
Feb 13, 2011, 11:53:43 PM2/13/11
to Ian Lance Taylor, golang-nuts
2011/2/14 Ian Lance Taylor <ia...@google.com>

Wei guangjing <vcc...@gmail.com> writes:

> I just make a patch for swig go support windows port, swig go really useful
> for bind c++ to go, please see the attachments for patch.

Thanks!  Can you also provide a patch which updates the documentation in
Doc/Manual/Go.html?

It would also be helpful to e-mail the patch to
swig-...@lists.sourceforge.net to see what the SWIG developers think
of it.

I will do it, thanks.

--
Wei guangjing

Jeroen Dirks

unread,
Feb 18, 2011, 4:58:51 PM2/18/11
to golang-nuts
Just a note for others.
This patch currently works on the latest SWIG version you get from
SVN.
Not the swigwin-2.0.1 release that you download from the website.
>  swig_go_windows.patch
> 8KViewDownload

Jeroen Dirks

unread,
Mar 28, 2011, 11:48:11 AM3/28/11
to golang-nuts
Hi Wei,

Do you think there is a way to use the dll created without hard coding
the executable name? I would like to build a generic package that uses
SWIG to wrap a C++ library.

With your Makefile it seems that the executable name is hard-coded.

Could that be avoided somehow?

Thanks,

Jeroen
>  swig_go_windows.patch
> 8KViewDownload

Wei guangjing

unread,
Mar 29, 2011, 10:24:49 AM3/29/11
to Jeroen Dirks, golang-nuts
2011/3/28 Jeroen Dirks <jeroen...@oracle.com>

Hi Wei,

Do you think there is a way to use the dll created without hard coding
the executable name? I would like to build a generic package that uses
SWIG to wrap a C++ library.

use GetProcAddress get .exe export functions form current process in swig wrap dll should works, that don't need hard coding the executable name.

--
Wei guangjing 


Wei guangjing

unread,
Apr 4, 2011, 5:27:47 AM4/4/11
to golang-nuts

Updated patch for build a generic package that use SWIG to wrap a C++ library, anyone have interesting can try the attached patch.
Only need -windows option to generate code for Windows.

BTW: I also sent this patch to SWIG-devel mail list.

2011/3/29 Wei guangjing <vcc...@gmail.com>
swig_go_windows2.patch

CrossWall

unread,
Jun 21, 2011, 4:27:57 PM6/21/11
to golan...@googlegroups.com
hope swig developer will accept the patch.

CrossWall

unread,
Jun 22, 2011, 3:33:52 PM6/22/11
to golan...@googlegroups.com
I can't get variables defined in C
but I can invoke functions defined in C.

All be capitalized.

the interface is
---------------------------
$ cat test.i
%module test
%{
    extern double MyVar;
    extern int Fact(int n);
    extern int MyMod(int x, int y);
    extern char *GetTime();
%}

extern double MyVar;
extern int Fact(int n);
extern int MyMod(int x, int y);
extern char *GetTime();
---------------------------
the source file
--------------------------
$ cat test.c
#include <time.h>
double MyVar = 3.0;

int Fact(int n) {
    if (n <= 1) return 1;
    else return n * Fact(n-1);
}

int MyMod(int x, int y) {
    return (x % y);
}

char *GetTime() {
    time_t ltime;
    time(&ltime);
    return ctime(&ltime);
}
-------------------------------------
go file
------------------------------------
$ cat main.go
package main

import "./test"

func main() {
    println(test.Fact(5))
    //println(test.MyVar)     //when uncomment this line show up "main.go:7: undefined: test.MyVar" error.
    println(test.MyMod(10, 3))
    println(test.GetTime())
}

Ian Lance Taylor

unread,
Jun 22, 2011, 3:47:16 PM6/22/11
to golan...@googlegroups.com
CrossWall <tiantia...@gmail.com> writes:

> I can't get variables defined in C
> but I can invoke functions defined in C.

SWIG will give you getter and setter functions. You can not directly
refer to variables defined in C++ from Go code.

> //println(test.MyVar) //when uncomment this line show up "main.go:7:
> undefined: test.MyVar" error.

test.GetMyVar()

Ian

Reply all
Reply to author
Forward
0 new messages