因此,我尝试通过动态加载在 C++ 项目上运行我的 go 代码。它工作得很好,除了返回值上有一些不需要的字符串。正如我解释的那样,我从 Go 那里得到了一些不需要的信息。我的代码:package mainimport "C"func main() {}//export GetTestStringfunc GetTestString() string { return "test"}我用以下方式构建它: go build -buildmode=c-shared -o test.so test.go使用此功能将其动态加载到我的 CPP 项目中:typedef struct { const char *p; ptrdiff_t n; } GoString;void getTestString() { void *handle; char *error; handle = dlopen ("./test.so", RTLD_LAZY); if (!handle) { fputs (dlerror(), stderr); exit(1); } // resolve getTestString symbol and assign to fn ptr auto getTestString = (GoString (*)())dlsym(handle, "GetTestString"); if ((error = dlerror()) != NULL) { fputs(error, stderr); exit(1); } // call GetTestString() GoString testString = (*getTestString)(); printf("%s\n", testString.p); // close file handle when done dlclose(handle);}输出是:" test true ...\n H_T= H_a= H_g= MB, W_a= and cnt= h_a= h_g= h_t= max= ptr siz= tab= top= u_a= u_g=, ..., fp:argp=falsefaultgcingpanicsleepsse41sse42ssse3 (MB)\n addr= base code= ctxt: curg= goid jobs= list= m->p= next= p->m= prev= span= varp=(...)\n, 不是 SCHED efenceerrno objectpopcntscvg: selectsweep (scan (scan) MB in Dying= locks= m->g0= nmsys= s=nil\n, goid=, size=, sys: GODEBUGIO waitSignal \ttypes \tvalue=cs fs gctracegs panic: r10 r11 r12 r13 r14 r15 r8 r9 rax rbp rbx rcx rdi rdx rflags rip rsi rsp runningsignal syscallunknownwaiting etypes goalΔ= is not mcount= minutes nalloc= newval= nfree..."
1 回答

冉冉说
TA贡献1877条经验 获得超1个赞
通过指向 C 的指针传递字符串时,您需要使用 length ( n) inGoString来获取正确数量的字符,因为字符串 atp未\0终止。或者您可以返回*C.char而不是string使用C.CString()在 C 堆上分配副本(然后您负责在使用后释放)。请参阅此处的Cgo 文档。
您的代码中发生的事情是printf()简单地打印从指向的位置开始的所有字符,string.p直到它到达\0终止符 - 这就是为什么您在test.
因此,您可以执行以下任一操作:
printf("%.*s\n", testString.n, testString.p);
(但请注意,大多数对预期\0终止的 C 字符串进行操作的函数将无法在此指针上工作,除非它们也占用字符串的长度)
或将 Go 部分更改为这样的内容,然后free()在 C 端使用后使用指针:
func GetTestString() *C.char {
return C.CString("test") // CString will allocate string on C heap
}
- 1 回答
- 0 关注
- 130 浏览
添加回答
举报
0/150
提交
取消