Передача строк между библиотеками на go и скриптами на Python

Рейтинг: 0Ответов: 1Опубликовано: 29.03.2023

Пытаюсь связать простой скрипт на Python с своей библиотекой на go. Код ниже. Смысл в том чтобы передать строку в библиотеку и получить полученное значение. Но выполнение кода вызывает ошибку со стороны go. Помогите разобраться, что я делаю не так. Код на Python:

import ctypes
lib = ctypes.CDLL("./lib.dll")
my_str = 'abc'
my_str_b = my_str.encode('utf-8')
c_str = ctypes.c_char_p(my_str_b)
my_new_str = lib.StringTest(c_str)
print(my_new_str)

Код на Golang:

package main
import (
    "C"
)

//export StringTest
func StringTest(my_val string) string {
    return my_val + "123"
}
func main() {}

Возникающая ошибка:

runtime: out of memory: cannot allocate 140733042393088-byte block (4128768 in use)
fatal error: out of memory

Ответы

▲ 3Принят

Правим код на golang, т.к. тип string на Go не является char* на С. Также возвращать string в CGO тоже нельзя будет ошибка вида cgo result has Go pointer, поэтому возвращаемый тип конвертируем в *C.char. Получается так:

package main

import (
    "C"
)

//export StringTest
func StringTest(my_val *C.char) *C.char {
    return C.CString(C.GoString(my_val) + "123")
}

func main() {}

Если выполнить код на python, то в my_new_str будет значение типа int. Это связано с тем что по умолчанию функции вызываемые через ctype возвращает значение типа int (return types ctypes). Поменяем тип возвращаемого значения для функции на ctypes.c_char_p и получим следующее:

import ctypes
lib = ctypes.CDLL("./lib.dll")
my_str = 'abc'
my_str_b = my_str.encode('utf-8')
c_str = ctypes.c_char_p(my_str_b)
lib.StringTest.restype = ctypes.c_char_p
my_new_str = lib.StringTest(c_str)
print(my_new_str)

Либо можно не выполнять преобразование строки ctypes.c_char_p, а передать bytes в качестве аргумента функции (спасибо @insolor, за то что указал в комментарии про такую возможность):

import ctypes
lib = ctypes.CDLL("./lib.dll")
my_str = 'abc'
lib.StringTest.restype = ctypes.c_char_p
my_new_str = lib.StringTest(my_str.encode('utf-8'))
print(my_new_str)