Update for Go 1.2 release. Add support for linking SWIG code directly

into executable, rather than using a shared library.
This commit is contained in:
Ian Lance Taylor 2013-12-16 19:50:17 -08:00
commit 1dca0af024
32 changed files with 385 additions and 371 deletions

View file

@ -22,6 +22,8 @@ class GO:public Language {
bool gccgo_flag;
// Prefix to use with gccgo.
String *go_prefix;
// Whether to use a shared library.
bool use_shlib;
// Name of shared library to import.
String *soname;
// Size in bits of the C type "long".
@ -86,6 +88,7 @@ public:
module(NULL),
gccgo_flag(false),
go_prefix(NULL),
use_shlib(false),
soname(NULL),
long_type_size(32),
intgo_type_size(0),
@ -153,6 +156,9 @@ private:
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i], "-use-shlib") == 0) {
Swig_mark_arg(i);
use_shlib = true;
} else if (strcmp(argv[i], "-soname") == 0) {
if (argv[i + 1]) {
soname = NewString(argv[i + 1]);
@ -274,7 +280,7 @@ private:
if (!package) {
package = Copy(module);
}
if (!soname) {
if (!soname && use_shlib) {
soname = Copy(package);
Append(soname, ".so");
}
@ -387,7 +393,7 @@ private:
Swig_banner(f_go_begin);
Printf(f_go_begin, "\n// source: %s\n", swig_filename);
if (!gccgo_flag) {
if (!gccgo_flag && soname) {
Swig_banner(f_gc_begin);
Printf(f_gc_begin, "\n/* source: %s */\n\n", swig_filename);
Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
@ -1084,6 +1090,7 @@ private:
Wrapper *f = NewWrapper();
Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
Printv(f->def, "#pragma cgo_import_static ", wname, "\n", NULL);
Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL);
Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
Printv(f->def, "\n", NULL);
@ -2825,6 +2832,7 @@ private:
Printv(f_c_directors, " crosscall2(", wname, ", &a, (int) sizeof a);\n", NULL);
Printv(f_gc_wrappers, "#pragma dynexport ", wname, " ", wname, "\n", NULL);
Printv(f_gc_wrappers, "#pragma cgo_export_static ", wname, " ", wname, "\n", NULL);
Printv(f_gc_wrappers, "extern void \xc2\xb7", go_name, "();\n", NULL);
Printv(f_gc_wrappers, "void\n", NULL);
Printv(f_gc_wrappers, wname, "(void *a, int32 n)\n", NULL);
@ -2918,17 +2926,20 @@ private:
return r;
}
String *go_upcall = NewString("Director");
Append(go_upcall, cn);
Append(go_upcall, go_name);
r = makeDispatchFunction(on, go_upcall, director_struct_name, is_static, director_struct_name, true);
if (r != SWIG_OK) {
return r;
if (!GetFlag(n, "abstract")) {
String *go_upcall = NewString("Director");
Append(go_upcall, cn);
Append(go_upcall, go_name);
r = makeDispatchFunction(on, go_upcall, director_struct_name, is_static, director_struct_name, true);
if (r != SWIG_OK) {
return r;
}
Delete(go_upcall);
}
Delete(cn);
Delete(go_name);
Delete(director_struct_name);
Delete(go_upcall);
Delete(go_name);
Delete(cn);
}
}
Setattr(class_methods, name, NewString(""));
@ -3010,6 +3021,11 @@ private:
Append(upcall_name, go_name);
String *upcall_wname = Swig_name_wrapper(upcall_name);
if (overname) {
Append(upcall_wname, overname);
}
String *upcall_gc_name = buildGoWrapperName(upcall_name, overname);
String *go_with_over_name = Copy(go_name);
if (overname) {
@ -3052,40 +3068,36 @@ private:
Printv(f_go_wrappers, "\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
// Declare the upcall function, which calls the method on the
// parent class.
if (!GetFlag(n, "abstract")) {
// Declare the upcall function, which calls the method on the
// parent class.
if (overname) {
Append(upcall_wname, overname);
if (gccgo_flag) {
Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
}
Printv(f_go_wrappers, "func ", upcall_gc_name, "(", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *tm = goWrapperType(p, Getattr(p, "type"), false);
Printv(f_go_wrappers, ", ", tm, NULL);
Delete(tm);
p = nextParm(p);
}
Printv(f_go_wrappers, ")", NULL);
if (SwigType_type(result) != T_VOID) {
String *tm = goWrapperType(n, result, true);
Printv(f_go_wrappers, " ", tm, NULL);
Delete(tm);
}
Printv(f_go_wrappers, "\n", NULL);
}
String *upcall_gc_name = buildGoWrapperName(upcall_name, overname);
if (gccgo_flag) {
Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
}
Printv(f_go_wrappers, "func ", upcall_gc_name, "(", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *tm = goWrapperType(p, Getattr(p, "type"), false);
Printv(f_go_wrappers, ", ", tm, NULL);
Delete(tm);
p = nextParm(p);
}
Printv(f_go_wrappers, ")", NULL);
if (SwigType_type(result) != T_VOID) {
String *tm = goWrapperType(n, result, true);
Printv(f_go_wrappers, " ", tm, NULL);
Delete(tm);
}
Printv(f_go_wrappers, "\n", NULL);
// Define the method on the director class in Go.
Printv(f_go_wrappers, "func (swig_p *", director_struct_name, ") ", go_with_over_name, "(", NULL);
@ -3136,181 +3148,189 @@ private:
}
Printv(f_go_wrappers, "\t}\n", NULL);
if (gccgo_flag) {
Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
}
Printv(f_go_wrappers, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_go_wrappers, "return ", NULL);
}
Printv(f_go_wrappers, upcall_gc_name, "(swig_p.", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
SwigType *pt = Getattr(p, "type");
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
if (goTypeIsInterface(p, pt)) {
Printv(f_go_wrappers, ".Swigcptr()", NULL);
if (GetFlag(n, "abstract")) {
Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
} else {
if (gccgo_flag) {
Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
}
p = nextParm(p);
Printv(f_go_wrappers, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_go_wrappers, "return ", NULL);
}
Printv(f_go_wrappers, upcall_gc_name, "(swig_p.", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
SwigType *pt = Getattr(p, "type");
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
if (goTypeIsInterface(p, pt)) {
Printv(f_go_wrappers, ".Swigcptr()", NULL);
}
p = nextParm(p);
}
Printv(f_go_wrappers, ")\n", NULL);
}
Printv(f_go_wrappers, ")\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
// Define a method in the C++ director class that the C++ upcall
// function can call. This permits an upcall to a protected
// method.
String *upcall_method_name = NewString("_swig_upcall_");
Append(upcall_method_name, name);
if (overname) {
Append(upcall_method_name, overname);
}
SwigType *rtype = Getattr(n, "classDirectorMethods:type");
String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0, 0);
Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
Delete(upcall_decl);
Printv(f_c_directors_h, " ", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_c_directors_h, "return ", NULL);
}
String *super_call = Swig_method_call(super, parms);
Printv(f_c_directors_h, super_call, ";\n", NULL);
Delete(super_call);
Printv(f_c_directors_h, " }\n", NULL);
// Define the C++ function that the Go function calls.
SwigType *first_type = NULL;
Parm *first_parm = parms;
if (!is_static) {
first_type = NewString("SwigDirector_");
Append(first_type, class_name);
SwigType_add_pointer(first_type);
first_parm = NewParm(first_type, "p", n);
set_nextSibling(first_parm, parms);
}
Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL);
Setattr(n, "wrap:name", upcall_wname);
String *action = NewString("");
if (SwigType_type(result) != T_VOID) {
Printv(action, Swig_cresult_name(), " = (", SwigType_lstr(result, 0), ")", NULL);
if (SwigType_isreference(result)) {
Printv(action, "&", NULL);
if (!GetFlag(n, "abstract")) {
String *upcall_method_name = NewString("_swig_upcall_");
Append(upcall_method_name, name);
if (overname) {
Append(upcall_method_name, overname);
}
}
Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", NULL);
SwigType *rtype = Getattr(n, "classDirectorMethods:type");
String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0, 0);
Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
Delete(upcall_decl);
p = parms;
int i = 0;
while (p != NULL) {
if (SwigType_type(Getattr(p, "type")) != T_VOID) {
String *pname = Swig_cparm_name(NULL, i + 1);
if (i > 0) {
Printv(action, ", ", NULL);
Printv(f_c_directors_h, " ", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_c_directors_h, "return ", NULL);
}
String *super_call = Swig_method_call(super, parms);
Printv(f_c_directors_h, super_call, ";\n", NULL);
Delete(super_call);
Printv(f_c_directors_h, " }\n", NULL);
// Define the C++ function that the Go function calls.
SwigType *first_type = NULL;
Parm *first_parm = parms;
if (!is_static) {
first_type = NewString("SwigDirector_");
Append(first_type, class_name);
SwigType_add_pointer(first_type);
first_parm = NewParm(first_type, "p", n);
set_nextSibling(first_parm, parms);
}
Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL);
Setattr(n, "wrap:name", upcall_wname);
String *action = NewString("");
if (SwigType_type(result) != T_VOID) {
Printv(action, Swig_cresult_name(), " = (", SwigType_lstr(result, 0), ")", NULL);
if (SwigType_isreference(result)) {
Printv(action, "&", NULL);
}
}
Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", NULL);
// A parameter whose type is a reference is converted into a
// pointer type by gcCTypeForGoValue. We are calling a
// function which expects a reference so we need to convert
// back.
if (SwigType_isreference(Getattr(p, "type"))) {
Printv(action, "*", NULL);
p = parms;
int i = 0;
while (p != NULL) {
if (SwigType_type(Getattr(p, "type")) != T_VOID) {
String *pname = Swig_cparm_name(NULL, i + 1);
if (i > 0) {
Printv(action, ", ", NULL);
}
// A parameter whose type is a reference is converted into a
// pointer type by gcCTypeForGoValue. We are calling a
// function which expects a reference so we need to convert
// back.
if (SwigType_isreference(Getattr(p, "type"))) {
Printv(action, "*", NULL);
}
Printv(action, pname, NULL);
Delete(pname);
i++;
}
Printv(action, pname, NULL);
Delete(pname);
i++;
p = nextSibling(p);
}
p = nextSibling(p);
}
Printv(action, ");", NULL);
Setattr(n, "wrap:action", action);
Printv(action, ");", NULL);
Setattr(n, "wrap:action", action);
if (!gccgo_flag) {
// Write the upcall wrapper function. This is compiled by gc
// and calls the C++ function.
int r = gcFunctionWrapper(n, upcall_name, upcall_name, overname, upcall_wname, first_parm, result, is_static, true);
if (r != SWIG_OK) {
return r;
if (!gccgo_flag) {
// Write the upcall wrapper function. This is compiled by gc
// and calls the C++ function.
int r = gcFunctionWrapper(n, upcall_name, upcall_name, overname, upcall_wname, first_parm, result, is_static, true);
if (r != SWIG_OK) {
return r;
}
r = gccFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
if (r != SWIG_OK) {
return r;
}
} else {
int r = gccgoFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
if (r != SWIG_OK) {
return r;
}
}
r = gccFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
if (r != SWIG_OK) {
return r;
Delete(first_type);
if (first_parm != parms) {
Delete(first_parm);
}
} else {
int r = gccgoFunctionWrapper(n, NULL, upcall_wname, first_parm, result);
if (r != SWIG_OK) {
return r;
Swig_restore(n);
Delete(upcall_method_name);
// Define a function that uses the Go director type that other
// methods in the Go type can call to get parent methods.
Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
String *tm = goType(p, Getattr(p, "type"));
Printv(f_go_wrappers, tm, NULL);
Delete(tm);
p = nextParm(p);
}
}
Delete(first_type);
if (first_parm != parms) {
Delete(first_parm);
}
Printv(f_go_wrappers, ")", NULL);
Swig_restore(n);
// Define a function which uses the Go director type that other
// methods in the Go type can call to get parent methods.
Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
String *tm = goType(p, Getattr(p, "type"));
Printv(f_go_wrappers, tm, NULL);
Delete(tm);
p = nextParm(p);
}
Printv(f_go_wrappers, ")", NULL);
if (SwigType_type(result) != T_VOID) {
String *tm = goType(n, result);
Printv(f_go_wrappers, " ", tm, NULL);
Delete(tm);
}
Printv(f_go_wrappers, " {\n", NULL);
if (gccgo_flag) {
Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
}
Printv(f_go_wrappers, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_go_wrappers, "return ", NULL);
}
Printv(f_go_wrappers, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
SwigType *pt = Getattr(p, "type");
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
if (goTypeIsInterface(p, pt)) {
Printv(f_go_wrappers, ".Swigcptr()", NULL);
if (SwigType_type(result) != T_VOID) {
String *tm = goType(n, result);
Printv(f_go_wrappers, " ", tm, NULL);
Delete(tm);
}
p = nextParm(p);
}
Printv(f_go_wrappers, ")\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
Printv(f_go_wrappers, " {\n", NULL);
if (gccgo_flag) {
Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
}
Printv(f_go_wrappers, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
Printv(f_go_wrappers, "return ", NULL);
}
Printv(f_go_wrappers, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
SwigType *pt = Getattr(p, "type");
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
if (goTypeIsInterface(p, pt)) {
Printv(f_go_wrappers, ".Swigcptr()", NULL);
}
p = nextParm(p);
}
Printv(f_go_wrappers, ")\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
}
// The Go function which invokes the method. This is called
// from by the C++ method on the director class.
@ -3390,17 +3410,16 @@ private:
}
Printv(f_go_wrappers, "\n", NULL);
Delete(upcall_gc_name);
}
Printv(f_go_wrappers, "}\n\n", NULL);
Delete(result_wrapper);
// Build the C++ functions.
Delete(upcall_wname);
Delete(upcall_gc_name);
// Build the C++ functions.
if (!gccgo_flag) {
Printv(f_c_directors, "extern \"C\" void ", callback_wname, "(void*, int);\n", NULL);
@ -3437,7 +3456,6 @@ private:
Printv(f_c_directors, " __asm__(\"", go_prefix, ".", package, ".", callback_name, "\");\n", NULL);
}
Delete(upcall_method_name);
Delete(go_with_over_name);
}
@ -3544,6 +3562,7 @@ private:
// 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, "#pragma cgo_export_static ", 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);
Printv(f_gc_wrappers, callback_wname, "(void *a, int32 n)\n", NULL);
@ -4909,5 +4928,6 @@ Go Options (available with -go)\n\
-longsize <s> - Set size of C/C++ long type--32 or 64 bits\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\
-use-shlib - Force use of a shared library\n\
-soname <name> - Set shared library holding C/C++ code to <name>\n\
\n";