Golang实现从共享库运行服务器的方案
Golang实现从共享库运行服务器的方案 尝试从共享库运行服务器,因此我执行了以下步骤:
- 编写共享库如下:
// server.go
package main
import (
"fmt"
"net/http"
)
import "C"
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
func headers(w http.ResponseWriter, req *http.Request) {
for name, headers := range req.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
}
}
}
func main() {}
// export Run server
func Run(port string) {
http.HandleFunc("/hello", hello)
http.HandleFunc("/headers", headers)
if err := http.ListenAndServe("localhost:"+port, nil); err == nil {
fmt.Println("listening to 8090")
} else {
fmt.Println("ListenAndServe: ", err)
}
}
- 编译共享库如下:
$ go build -buildmode c-shared -o server.so server.go
- 编写调用共享库中
Run函数的主文件如下:
//main.go
package main
/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>
void Run(char* port){}
*/
import "C"
func main() {
// handle := C.dlopen(C.CString("server.so"), C.RTLD_LAZY)
// C.dlsym(handle, C.CString("8090"))
C.dlopen(C.CString("server.so"), C.RTLD_LAZY)
C.run(C.CString("8090"))
}
- 运行主文件如下:
$ go run main.go
主函数直接终止了,服务器并未在 http://localhost:8090/hello 地址上运行。
更多关于Golang实现从共享库运行服务器的方案的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
你似乎是在非 Windows 系统上运行,因此我建议研究一下 plugin 包。
更多关于Golang实现从共享库运行服务器的方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的方案存在几个关键问题。以下是修正后的实现:
- 共享库需要正确导出函数:
// server.go
package main
import (
"fmt"
"net/http"
)
import "C"
//export Run
func Run(port *C.char) {
http.HandleFunc("/hello", hello)
http.HandleFunc("/headers", headers)
goPort := C.GoString(port)
addr := "localhost:" + goPort
fmt.Printf("Starting server on %s\n", addr)
if err := http.ListenAndServe(addr, nil); err != nil {
fmt.Printf("ListenAndServe error: %v\n", err)
}
}
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
func headers(w http.ResponseWriter, req *http.Request) {
for name, headers := range req.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
}
}
}
func main() {}
编译共享库:
go build -buildmode=c-shared -o server.so server.go
- 主程序需要正确加载和调用共享库函数:
// main.go
package main
/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>
#include <stdlib.h>
typedef void (*RunFunc)(char*);
void callRun(void* handle, char* port) {
RunFunc run = (RunFunc)dlsym(handle, "Run");
if (run != NULL) {
run(port);
}
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
// 加载共享库
libPath := C.CString("./server.so")
defer C.free(unsafe.Pointer(libPath))
handle := C.dlopen(libPath, C.RTLD_LAZY)
if handle == nil {
fmt.Printf("Failed to load library: %s\n", C.GoString(C.dlerror()))
return
}
defer C.dlclose(handle)
// 调用Run函数
port := C.CString("8090")
defer C.free(unsafe.Pointer(port))
C.callRun(handle, port)
// 保持主程序运行
select {}
}
- 或者使用更简洁的cgo直接调用方式:
// main_simple.go
package main
/*
#cgo LDFLAGS: -L. -lserver
#include <stdlib.h>
extern void Run(char* port);
*/
import "C"
import (
"time"
)
func main() {
port := C.CString("8090")
defer C.free(unsafe.Pointer(port))
C.Run(port)
// 保持程序运行
for {
time.Sleep(time.Hour)
}
}
编译并运行:
# 编译共享库
go build -buildmode=c-shared -o libserver.so server.go
# 运行主程序
go run main.go
关键修正点:
- 使用
//export Run注释正确导出函数 - 在C代码中声明函数指针类型并正确调用dlsym
- 主程序需要保持运行(使用select{}或for循环)
- 添加必要的错误处理
- 使用goroutine安全的字符串转换
服务器将在 http://localhost:8090/hello 正常运行。

