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

Другие вопросы по тегам