我现在就是这么做的,
.
├── helloworld--1.0.sql
├── helloworld.control
├── helloworld.go
└── Makefilehelloworld.go:
package helloworld
/*
#cgo LDFLAGS: -rdynamic
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(helloworld);
PG_FUNCTION_INFO_V1(hello_text_arg);
PG_FUNCTION_INFO_V1(hello_ereport);
Datum
hello_world(PG_FUNCTION_ARGS)
{
PG_RETURN_TEXT_P(cstring_to_text("Hello, World!"));
}
Datum
hello_text_arg(PG_FUNCTION_ARGS)
{
text *hello = cstring_to_text("Hello, ");
int32 hello_sz = VARSIZE(hello) - VARHDRSZ;
text *name = PG_GETARG_TEXT_P(0);
int32 name_sz = VARSIZE(name) - VARHDRSZ;
text *tail = cstring_to_text("!");
int32 tail_sz = VARSIZE(tail) - VARHDRSZ;
int32 out_sz = hello_sz + name_sz + tail_sz + VARHDRSZ;
text *out = (text *) palloc(out_sz);
SET_VARSIZE(out, out_sz);
memcpy(VARDATA(out), VARDATA(hello), hello_sz);
memcpy(VARDATA(out) + hello_sz, VARDATA(name), name_sz);
memcpy(VARDATA(out) + hello_sz + name_sz, VARDATA(tail), tail_sz);
PG_RETURN_TEXT_P(out);
}
Datum
hello_ereport(PG_FUNCTION_ARGS)
{
ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed")));
PG_RETURN_VOID();
}
*/
import "C"Makefile:
MODULES = helloworld
EXTENSION = helloworld
DATA = helloworld--1.0.sql
PGFILEDESC = "helloworld - example extension for postgresql"
REGRESS = helloworld
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server)
include $(PGXS)
helloworld.so:
CGO_CFLAGS="-rdynamic -I$(INCLUDEDIR)" CGO_LDFLAGS="-rdynamic $(LDFLAGS)" go build -v -buildmode=c-shared -o helloworld.so .它在犯下列错误时产生了这些错误:
/tmp/go-build019341122/github.com/amosbird/rpctest/helloworld/_obj/helloworld.cgo2.o: In function `hello_world':
helloworld.cgo2.c:(.text+0x48): undefined reference to `cstring_to_text'
/tmp/go-build019341122/github.com/amosbird/rpctest/helloworld/_obj/helloworld.cgo2.o: In function `hello_text_arg':
helloworld.cgo2.c:(.text+0x63): undefined reference to `cstring_to_text'
helloworld.cgo2.c:(.text+0x86): undefined reference to `pg_detoast_datum'
helloworld.cgo2.c:(.text+0xa5): undefined reference to `cstring_to_text'
helloworld.cgo2.c:(.text+0xd7): undefined reference to `palloc'
/tmp/go-build019341122/github.com/amosbird/rpctest/helloworld/_obj/helloworld.cgo2.o: In function `hello_ereport':
helloworld.cgo2.c:(.text+0x1a8): undefined reference to `errstart'
helloworld.cgo2.c:(.text+0x1bd): undefined reference to `errmsg'
helloworld.cgo2.c:(.text+0x1c9): undefined reference to `errcode'
helloworld.cgo2.c:(.text+0x1d7): undefined reference to `errfinish'
collect2: ld returned 1 exit status
make: *** [helloworld.so] Error 2我不知道这是否可行。这里发生了那么多黑魔法。
因此,主要的问题是,在cgo中构建Postgres扩展的正确Makefile是什么?
针对这些错误的一个具体问题是,在cgo的链接过程中,我能做些什么来推迟这些符号的解析?
发布于 2017-01-04 14:32:17
好吧,我花了一整天找到了一个可行的解决方案。
我们需要以扩展名的主源文件开头:
package main // make sure to use main package
/*
#cgo CFLAGS: -I/path/to/postgres/include/server
#cgo LDFLAGS: -Wl,-unresolved-symbols=ignore-all使用go build -o myext.so -buildmode=c-shared myext.go生成myext.so。
如果需要C端的Go方法,我们应该在方法声明的前面添加//export methodname。这将生成没有包名前缀的符号。然后我们就可以把这些符号在C边导出。确保导出的Go方法驻留在main以外的包中。
package test:
//export Merge
func Merge(cint C.int) C.int ...package main:
extern int Merge(int);
import "./test"
var _ = test.Somevar // dumb placeholder to fake use package test.https://stackoverflow.com/questions/41456777
复制相似问题