const
(только для C ++) Для людей, прибывающих с C, может показаться неожиданным, что в C ++ глобальные переменные const
имеют внутренние (или статические) связь. В C это не так, поскольку все глобальные переменные неявно extern
(т.е. когда отсутствует ключевое слово static
).
Пример:
// file1.cpp
const int test = 5; // in C++ same as "static const int test = 5"
int test2 = 5;
// file2.cpp
extern const int test;
extern int test2;
void foo()
{
int x = test; // linker error in C++ , no error in C
int y = test2; // no problem
}
correct would использовать файл заголовка и включить его в file2.cpp и file1.cpp
extern const int test;
extern int test2;
. В качестве альтернативы можно было бы объявить переменную const
в файле file1.cpp с явным extern
Обновление: теперь возможно сделать это в mainline Go, см. Режимы выполнения Go
Из примечаний к выпуску Go 1.5 :
Только для архитектуры amd64 у компилятора есть новая опция -dynlink, которая помогает динамической компоновке, поддерживая ссылки на символы Go, определенные во внешних разделяемых библиотеках.
blockquote>Старый ответ ( полезное обсуждение других опций ):
В настоящее время невозможно создать динамически связанные библиотеки * в главной строке Go. Об этом говорили некоторые, поэтому вы можете увидеть поддержку в будущем. Тем не менее, существует проект стороннего проекта под названием goandriod , который нуждается в той же функциональности, в которой вы нуждаетесь, поэтому они поддерживают исправления, которые должны позволить вам исправлять официальную базу кода Go, чтобы поддерживать динамическую связанную поддержку, которую вы запрашиваете .
Если вы хотите использовать стандартное время выполнения Go, я бы порекомендовал одно из следующего. Вызовите свою программу Go из своей другой программы и обменивайтесь ею с помощью:
- Трубы для связи
- Сокет домена UNIX
- Монументированный регион общей памяти , То есть создайте файл на / dev / shm и у вас есть обе программы mmap. Перейти к библиотеке mmap: https://github.com/edsrzf/mmap-go
Каждый последовательный вариант потребует больше усилий для настройки, но потенциально более мощным, чем предыдущий.
* Примечание. Это DLL в мире Windows и .so файлы в мире UNIX / Linux.
Возможность создания разделяемых библиотек будет в Go 1.5 в августе 2015 года.
От « Состояние Go » говорит Andrew Gerrand:
Общие библиотеки
Go 1.5 может создавать общие библиотеки, которые могут быть использованы программами Go.
Построить стандартную библиотеку в качестве общих библиотек:
$ go install -buildmode=shared std
Создайте программу «Hello, world», которая связывается с разделяемыми библиотеками:
$ go build -linkshared hello.go $ ls -l hello -rwxr-xr-x 1 adg adg 13926 May 26 02:13 hello
Go 1.5 также может создавать программы Go в виде файлов архива C (для статической привязки) или разделяемых библиотек (для динамических link), которые могут быть использованы программами C.
[см.]: golang.org/s/execmodes
blockquote>¹ Примечание,
gccgo
уже в течение некоторого времени поддерживала ограниченную поддержку, Go 1.5 будет в первый раз поддерживаться обычными инструментами сборки go.
Feature promiced since 1.5 :) http://talks.golang.org/2015/state-of-go-may.slide#23
Это очень возможно, вы даже можете скомпилировать его как собственную общую библиотеку
go build -buildmode=c-shared goc.go
# file goc
goc: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV),
dynamically linked,
BuildID[sha1]=f841e63ee8e916d7848ac8ee50d9980642b3ad86,
not stripped
nm -D --defined-only ./goc | grep "T"
0004ebe8 T _cgoexp_f88ec80374ab_PrintInt
000a6178 T _cgo_panic
0004e954 T _cgo_sys_thread_start
000a48c8 T _cgo_topofstack
0004e88c T _cgo_wait_runtime_init_done
000a61a4 T crosscall2
0004ebc8 T crosscall_arm1
0004e7b0 T fatalf
00102648 T _fini
0004e544 T _init
0004e76c T PrintInt
0004ebe4 T __stack_chk_fail_local
0004eb5c T x_cgo_free
0004ea60 T x_cgo_init
0004eb24 T x_cgo_malloc
0004e8e0 T x_cgo_notify_runtime_init_done
0004eb14 T x_cgo_setenv
0004e820 T x_cgo_sys_thread_create
0004eb64 T x_cgo_thread_start
0004eb20 T x_cgo_unsetenv
, подобный так (проверено на go 1.5.1 linux / arm)
goc.go:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
// http://stackoverflow.com/questions/32215509/using-go-code-in-an-existing-c-project
// go build -buildmode=c-archive goc.go
// go build -buildmode=c-shared goc.go
// https://groups.google.com/forum/#!topic/golang-nuts/1oELh6joLQg
// Trying it on windows/amd64, looks like it isn't supported yet. Is this planned for the 1.5 release?
// It will not be in the 1.5 release.
// It would be nice if somebody worked on it for 1.6.
// https://golang.org/s/execmodes
// http://stackoverflow.com/questions/19431296/building-and-linking-dynamically-from-a-go-binary
// go build -linkshared hello.g
// go install -buildmode=shared std
func main() {
fmt.Println("Hello world")
}
Я думаю, что go плагины могут быть также связаны с этим вопросом, они поддерживаются с версии 1.8. Это позволяет вам динамически связывать исполняемые файлы, реализующие требуемые интерфейсы во время выполнения.
Например, ваш код имеет зависимость для бэкэнда ведения журнала, но вы хотите поддержать несколько из них и разрешить его во время выполнения elasticsearch
и splunk
. Возможно, вам необходимо иметь 2 файла: es.go
и splunk.go
, которые должны содержать структуру типа LoggingBackend
, реализующую метод Write(log string)
.
Для создания плагинов вам необходимо использовать buildmode plugin
во время компиляции:
go build -buildmode = plugin -o es.so es.go
go build -buildmode = plugin -o splunk.so splunk.go
blockquote>После этого вы можете передать необходимый плагин через аргументы командной строки и загрузить его:
package main import "plugin" import "flag" type LoggingBackend interface { Write(log string) } var ( backend = flag.String("backend", "elasticsearch", "Default logging backend is elasticsearch") ) func main() { flag.Parse() var mode string switch backend { case "elasticsearch": mode = "./es.so" case "splunk": mode = "./splunk.so" default: fmt.Println("Didn't recognise your backend") os.Exit(1) plug, _ := plugin.Open(mod) loggingBackend, _ := plug.Lookup("LoggingBackend") logWriter, _ := loggingBackend.(LoggingBackend) logWriter.Write("Hello world") }