首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用cgo构建Postgres扩展

如何使用cgo构建Postgres扩展
EN

Stack Overflow用户
提问于 2017-01-04 05:27:15
回答 1查看 588关注 0票数 1

我现在就是这么做的,

代码语言:javascript
复制
.
├── helloworld--1.0.sql
├── helloworld.control
├── helloworld.go
└── Makefile

helloworld.go

代码语言:javascript
复制
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

代码语言:javascript
复制
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 .

它在犯下列错误时产生了这些错误:

代码语言:javascript
复制
/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的链接过程中,我能做些什么来推迟这些符号的解析?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-04 14:32:17

好吧,我花了一整天找到了一个可行的解决方案。

我们需要以扩展名的主源文件开头:

代码语言:javascript
复制
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

代码语言:javascript
复制
//export Merge
func Merge(cint C.int) C.int ...

package main

代码语言:javascript
复制
extern int Merge(int);

import "./test"
var _ = test.Somevar  // dumb placeholder to fake use package test.
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41456777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档