Cgo: не могу найти способ использовать обратные вызовы с аргументом const char*
Я использую библиотеку C из Go с использованием Cgo и все хорошо, кроме обратных вызовов. Библиотека имеет функцию обратного вызова, которая принимает указатель на функцию обратного вызова. Функция обратного вызова сама написана на go и экспортирована с использованием синтаксиса Cgo.
Проблема: я могу сделать и экспортировать функцию с char *
аргумент, но не могу с const char *
,
Код для иллюстрации:
test.go:
package main
/*
typedef void (*cb_func)(const char *, int);
void callback(cb_func);
void myFunc(const char *, int);
*/
import "C"
import (
"fmt"
"unsafe"
)
//export myFunc
func myFunc(buf *C.char, ln C.int) {
fmt.Printf("Got: %s\n", C.GoStringN(buf, ln))
}
func main() {
C.callback((C.cb_func)(unsafe.Pointer(C.myFunc)))
}
test.c:
typedef void (*cb_func)(const char *, int);
void callback(cb_func cb) {
cb("test", 4);
}
Выход из go build
:
In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:54:13: error: conflicting types for 'myFunc'
./test.go:7:6: note: previous declaration of 'myFunc' was here
void myFunc(const char *, int);
^
/tmp/go-build994908053/test/_obj/_cgo_export.c:9:6: error: conflicting types for 'myFunc'
void myFunc(char* p0, int p1)
^
In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:7:6: note: previous declaration of 'myFunc' was here
void myFunc(const char *, int);
^
Без const
классификатор кода компилируется и работает как положено.
Что можно использовать вместо *C.char
получить константную строку в C?
1 ответ
С го нет const
В модификаторах для указателей нет способа перевести это поведение изнутри кода Go. cgo всегда будет генерировать заголовки, которые не имеют const
модификатор. Это также причина, почему ваш код не собирается правильно: cgo
создает myFunc
только исходя из того что знает: buf
должно быть char*
не const char*
,
Лучший способ справиться с этим - использовать оболочку на стороне C, которая приводит этот параметр к const char*
, В вашем случае достаточно изменить определение myFunc
в void myFunc(char*, int)
, Передача функции cb_func
будет работать независимо от кастинга myFunc
в (*cb_func)(const char*,int)
только добавляет информацию о типе, но не меняет структуру памяти.
Я была такая же проблема. Одно из решений для все еще нуждающегося - это что-то вроде:
typedef const char cchar_t
void myNewFunction(cchar_t* data);
затем используйте его как data* C.char_t