Hello All,

I'm using Go1.8  mostly with plugins on Linux x86-64  (and I am only 
interested in Go since it has plugins, since I love the idea of having my 
monimelt <https://github.com/bstarynk/monimelt> program -GPL code on 
gitbub-  emit at *runtime* some Go "source" code, in some temporary file, 
fork a compilation of that emitted source code into a plugin at runtime, 
and load that plugin and call code inside it, all that from the same 
process at runtime). See this question 
<https://groups.google.com/forum/#!topic/golang-nuts/IKh1BqrNoxI> and also 
https://blog.ksub.org/bytes/2017/02/12/exploring-shared-objects-in-go/ 

 BTW, for C or C++ code doing all this is quite easy (see for example my 
manydl.c <https://github.com/bstarynk/misc-basile/blob/master/manydl.c> as 
simple example, or for a much more serious thing my GCC MELT 
<http://gcc-melt.org/>) once you understood that the main loading program 
should be linked with the -rdynamic flag and with the -ldl library (and 
will use dlopen(3) <http://man7.org/linux/man-pages/man3/dlopen.3.html> so 
its source code should #include <dlfcn.h>) : one just emit some C code in a 
temporary file like /tmp/emittedcode.c, run (e.g. with system(3) 
<http://man7.org/linux/man-pages/man3/system.3.html> ...) some careful 
compilation command into a plugin like gcc -shared -fPIC -O -Wall -g 
/tmp/emittedcode.c -o /tmp/emittedcode.so .... and load the plugin using 
void*plugin = dlopen("/tmp/emittedcode.so", RTLD_NOW | RTLD_GLOBAL);
(I'm ignoring here error handling at dlopen stage). At last we should 
retrieve some symbol, e.g. some int returning function emittedfoo of two int 
arguments in that /tmp/emittedcode.{c,so} using code like
typedef int sigfuntype (int,int); // signature of emitted function
sigfuntype* emittedfunptr = (sigfuntype*) dlsym(plugin, "emittedfoo");
(again, ignoring handling of dlsym failure). Later the main loading program 
could use that function pointer e.g. like
int y = emittedfunptr(2,3);
and so on. Notice that with gcc passing -v -H helps a lot: it explains 
what  files are read and what files are written by the gcc compiler. And 
sharing some code between a plugin and the loading program is easy (once 
-rdynamic is used to link the loading program): the plugin should just 
declare functions (in practice, #include some header from the program 
source directory) of the loading program and call them. 

I am able to code similar things in Ocaml, because I understand where the 
Ocaml compiler is putting information about plugins (in .cmxs files) and 
about modules (their interface is described by .cmi files).


 I am aware that I am using Go in some unusual way. Of course I want the 
plugin to have some packages, and to use some other packages provided by 
the main program. Of course I don't want binary code to be duplicated, so I 
need some binary shared code, that is the -linkshared and -buildmode=shared 
options are very important to me.

I don't understand as much for the Go compiler, using the go tool. In 
particular I have a very *incomplete* understanding about :

what is the exact structure and content of a Go compiled package file? 
Apparently it is some ar archive with __.PKGDEF & _go_.o members. Why?  
What are appropriate tools to inspect these package files?
sometimes, it looks like the Go compiler is using HTTP requests to fetch 
source code (e.g. from github). When does that happen? What kind of HTTP 
requests? 
where is the output going for a given go command?
What is the *exact* effect of -linkshared and of -buildmode=shared ?
How does the compilation works?. I have the intuition (perhaps wrongly) 
that in many cases only the package and the import statements are parsed in 
.go files? When does that happens, and when is the file entirely parsed?
What is the effect of import <https://golang.org/ref/spec#ImportPath> and 
what exactly does the import path means ? What exacty is the import comment 
<https://golang.org/s/go14customimport>?And custom imports? Their relation 
with -linkshared? 

I badly miss some equivalent for go of the -H option for gcc. In my dreams, 
I would like some -show option which would display the complete file path 
of successfully read files, and the complete URL of successful HTTP GET 
requests, and the complete file path of successfully written files. If that 
is easy to implement (and I believe it is), could someone explain me what 
files and functions of the compiler should I patch?

I believe I am not alone in wanting this. I notice that many talks are 
proposing alternative builders (such as gb <https://getgb.io/>, which sadly 
is plugin incompatible today, or glide <https://glide.sh/>), or using 
Makefile with go, etc. I would be quite happy using some Makefile for Go 
with plugins, but sadly I am unable to write it (because of my 
misunderstanding of go tool and packages).

I confess that I am blocked since several weeks because of such issues, and 
I am considering (sadly) giving up Go (and sadly going back to emit C or 
C++ code at runtime, like I did in the past). I would miss Go concurrent 
abilities and its multi-thread friendly garbage collector.



My misunderstanding of Go internals -in particular with plugins and shared 
code in mind- is making me unhappy.


I am willing, if so needed, to describe in every detail what I have tried 
in my monimelt <https://github.com/bstarynk/monimelt> project (on Github).

If you are in France, in the Paris region, I can even go to your place with 
my laptop (But the people I have met at the recent Go meetup  in Paris are 
not able to help because they don't care about plugins).

Thanks for reading. Regards.

-- 
Basile Starynkevitch <http://starynkevitch.net/Basile/> (France) 
bas...@starynkevitch.net 



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to