es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cadena desconocida de Golang cargada dinámicamente hacia CPP

Entonces, intenté ejecutar mi código Go en un proyecto C++ con carga dinámica. Funciona muy bien, excepto que hay una cadena no deseada en el valor devuelto. Como expliqué antes, obtuve algunas información no deseadas de Go.

Mi código Go:

package main

import "C"

func main() {}

//export GetTestString
func GetTestString() string {
    return "test"
}

Lo construyo con:

go build -buildmode=c-shared -o test.so test.go

Cargo dinámicamente en mi proyecto CPP con esta función:

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);
    }

    // resuelvo el símbolo getTestString y lo asigno a un puntero de función
    auto getTestString = (GoString (*)())dlsym(handle, "GetTestString");
    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    // llamo a GetTestString()
    GoString testString = (*getTestString)();
    printf("%s\n", testString.p);

    // cierro el archivo cuando haya terminado
    dlclose(handle);
}

La salida es:

“test”true …\n HT= Ha= Hg= MB, Wa= and cnt= ha= hg= ht= max= ptr siz= tab= top= ua= 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…”

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que la salida no solo es la cadena esperada “test”, sino que también contiene información adicional no deseada. Esto podría ser debido a varios motivos, como una asignación de memoria incorrecta o una incompatibilidad entre los tipos de datos de C++ y Go.

    Una posible solución es utilizar el tipo de dato const char* de C en lugar del tipo string de Go para el tipo de retorno de la función GetTestString. Esto se puede lograr modificando el código de Go de la siguiente manera:

    package main
    
    import "C"
    import "unsafe"
    
    func main() {}
    
    //export GetTestString
    func GetTestString() *C.char {
        return C.CString("test")
    }
    

    Luego, en el código de C++, podemos actualizar la definición de la estructura GoString para que utilice const char* en lugar de string. Además, debemos liberar la memoria asignada por C.CString() una vez que hayamos terminado de usar la cadena devuelta.

    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);
        }
    
        // resolver el símbolo getTestString y asignarlo al puntero de función
        auto getTestString = (const char*(*)())dlsym(handle, "GetTestString");
        if ((error = dlerror()) != NULL)  {
            fputs(error, stderr);
            exit(1);
        }
    
        // llamar a GetTestString()
        const char* testString = (*getTestString)();
        printf("%s\n", testString);
    
        // liberar la memoria asignada por C.CString()
        free((void*)testString);
    
        // cerrar el archivo cuando hayamos terminado
        dlclose(handle);
    }
    

    Con estos cambios, la salida solo debería contener la cadena esperada “test”.

Comments are closed.