从 Dynamic Loaded Golang 到 CPP 的未知字符串

Unknown string from Dynamic Loaded Golang to CPP

所以,我尝试 运行 我的 go 代码在 C++ 项目上动态加载。它工作得很好,除了返回值上有一些不需要的字符串。正如我解释的那样,我从 Go 那里得到了一些不需要的信息。

我的代码:

package main

import "C"

func main() {}

//export GetTestString
func 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);
}

输出为:

"testtrue ...\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, not 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..."

当通过指向 C 的指针传递字符串时,您需要在 GoString 中使用长度 (n) 来获取正确数量的字符,因为 p 处的字符串不是 [=15= ] 终止。或者您可以 return *C.char 而不是 string 并使用 C.CString() 在 C 堆上分配副本(然后您负责在使用后释放)。请参阅 Cgo 文档 here

你的代码中发生的事情是 printf() 简单地打印从 string.p 指向的位置开始的所有字符,直到它到达 [=15=] 终止符 - 这就是你看到内存内容的原因在 test.

之后

因此您可以执行以下任一操作:

printf("%.*s\n", testString.n, testString.p);

(但请注意,大多数对预期 [=15=] 终止的 C 字符串进行操作的函数将不适用于此指针,除非它们也采用字符串的长度)

或将 Go 部分更改为类似这样的内容,然后在 C 端使用后 free() 指针:

func GetTestString() *C.char {
    return C.CString("test") // CString will allocate string on C heap
}