Transferred from: http://blog.csdn.net/xtxy/article/details/21328143
In the use of LUA server-side game logic development, found a variety of Lua inconvenient places, can not compile check, not breakpoint debugging, clerical functions and variables do not prompt error, etc., so have all use go to do server-side development ideas.
If you do not need a hot update, that use go to develop server logic is very easy, and game server especially page tour, generally need to support hot update, so I decided to use Go dynamic link library approach to implement, that is, the underlying framework is go, the upper logic is go dynamic link library. Go native does not support dynamic link libraries, after reviewing many articles, decided to use GCCGO to achieve.
After about a week, finally the framework was set up, during the period encountered some of the problems of the pit, recorded here so that it will not be repeated, but also to help other students with the same needs to quickly build such a framework.
This example needs to understand the Go directory build and environment variables knowledge, if you do not understand, you can first look at the online article, very simple.
The way the whole frame is built is goccgo, that is, go---c--dll---C--go. The bottom and top are go, and C is used in the middle to provide a way to dynamically link libraries.
1 First look at the bottom of the special place, is the go->c part.
The go file is as follows:
//Script.goPackage Script//1//extern InitdllFunc C_initdll (string,string)//extern runDllFunc C_rundll (string, map[string]Interface{})stringvarDataMap map[string]Interface{}//2func Init (fileNamestring, FuncNamestring) {DataMap= Make (map[string]Interface{}) returnC_initdll (FileName, FuncName)}func Run (buf []byte)string{str:=string(BUF) Retstr:=C_rundll (str, DATAMAP)returnRetstr}
1 of them are GCCGO's special wording,//extern funcname means that there is a C function, in go use C_funcname to invoke it. (Is it possible to use other names I have not tried)
2 is the declaration of a map structure, which is said later, at this time, regardless of the first.
The init function in the file is called when the program starts and is used to load the Dll;run function to call the DLL to handle the game logic every time.
The corresponding C files are as follows:
//script.c#include<dlfcn.h>struct__go_string {//1 ConstUnsignedChar*__data; int__length;};struct__go_string (*dllentry) (struct__go_string,int);//2voidLoaddll (struct__go_string FileName,struct__go_string FuncName) { void*dll = Dlopen (Filename.__data, Rtld_lazy);//3 if(!dll) {//Error} dlerror (); *(void* *) (&dllentry) = Dlsym (DLL, funcname.__data);//4 if(NULL! =Dlerror ()) { //Error }}struct__go_string RunDll (struct__go_string InData,void*DataMap) { returnDllentry (InData, DATAMAP);//5}
Of these, 1 is the representation of the string type in C in Go, and the string is a struct in C.
2 is the main function of the dynamic link library, and the dynamic link library exports this function to deal with the game logic.
3 and 4 are the code that loads the dynamic-link library and gets the function address, respectively.
5 is where the main function of the dynamic link library is called, and the example passes the argument as a string and a pointer (which is actually the address of the map), and the return value is also a string.
Here's how to compile them:
Gccgo-o testc.o-c test.c
Gccgo-o testgo.o-c Test.go
AR cr libtest.a testgo.o TESTC.O
The final compiled libtest.a need to be placed under the PKG directory corresponding to the place. That is where you put the generated library when you use the Go Install command, and you tell libtest.a where to copy it.
The part of the GO->C has been completed.
2 The interface of the dynamic link library, the C->go part
The C file is as follows:
//dll.cstruct__go_string {ConstUnsignedChar*__data; int__length;};extern struct__go_string Go_entry (struct__go_string,int,void*) __asm__ ("Gamelogic_ctrl. Entry");//1//void __attach (void) __attribute__ ((constructor));//2struct__go_string Centry (struct__go_string input,void*DataMap) { returngo_entry (input, DATAMAP);}
1 is the C call go function declaration, entry is the function name, Gamlogic_ctrl is the package name, if this place error, you can use the NM command to see the go generated lib file, the package name modified correctly.
2 is the initialization function declaration of the dynamic Link library, if necessary, you can add one, call go function, do some initialization operation.
The corresponding go files are as follows:
// Dllmain.go stringint, DataMap map[string]interfacestring { return""}
It is the same as the normal go file.
Here's how to compile them:
Go install-compiler=gccgo-gccgoflags= '-fpic '//compile all the Go files
Gccgo-o libcdll.a-c dll.c-fpic//Compile the DLL portal's C file
Then copy the LIBCDLL.A to the directory of the other go-generated libraries and execute:
Gccgo-shared-o dllmain.so *.a//compiling a single library file into the final dynamic link library
The entire framework dynamic link library section is complete.
Let me say what you need to be aware of when using this framework:
1. When compiling the dynamic link library, other than the C part, do not use the GCCGO command directly, because some external libraries, such as the MgO library to access MongoDB, you can not use Gccgo compiled (or very difficult), the simplest way is to use go Install-compiler The way of =gccgo;
2. The dynamic link library does not perform the initialization part, i.e. the INIT function in the package is not called;
3. As compared to the above, import external libraries (including system libraries), such as FMT, are not import. The solution is to import all the libraries that the dynamic link library needs to use in the basic framework section (i.e., the executable file);
4. The memory requested in the dynamic link library will be released after the call is completed. For example, in the dynamic link library main function file (the last file containing the entry function), add a package inside the global variable: var tmpmap = make (map[string]interface{}), if the entry function to access Tmpmap, You will find that the map space that Tmpmap points to has been released, and it will report a segment error. The workaround is to declare a map structure in the underlying framework and then pass it on to the dynamic link library, which will not be freed from the map data. That is, in note 2 of the first file I enumerated (script.go), a datamap is declared, which is the function.
5. In Gccgo's documentation, slice can be passed as a function parameter between C and go, but after I have tried it, I find a problem. The first is go slice to C inside, not a struct, but a struct *, is said to be a pointer, and I will point to the memory of the pointer to print out, and the document is completely right, not to find the character array, the location of the Len can not be found, The position of the cap seems to be offset 4 bytes upward in this pointer ... I got caught, and there was no research, and strings were used instead of slice for transmission.
Because it is self-groping out of things, so there may be some places are not correct, I hope you correct me, I revise at any time.
The use of the dynamic link library of Go under Linux