как я могу получить указатель данных строковой переменной в go?

Я хочу получить указатель данных строковой переменной (например, string::c_str() в С++) для передачи функции c, и я обнаружил, что это не работает:

package main

/*
#include <stdio.h>
void Println(const char* str) {printf("%s\n", str);}
*/
import "C"

import (
    "unsafe"
)

func main() {
    s := "hello"
    C.Println((*C.char)(unsafe.Pointer(&(s[0]))))
}

Информация об ошибке компиляции: «невозможно принять адрес s[0]». Это будет нормально, но я сомневаюсь, что это вызовет ненужное использование памяти. Есть ли лучший способ получить указатель данных?

C.Println((*C.char)(unsafe.Pointer(&([]byte(s)[0]))))

person Toby    schedule 27.02.2017    source источник


Ответы (1)


Есть способы получить базовые данные из строки Go в C без их копирования. Это не будет работать как строка C, потому что это не строка C. Ваш printf не будет работать, даже если вам удастся извлечь указатель, даже если иногда он работает. Строки Go не являются строками C. Раньше они были для совместимости, когда Go использовал больше libc, теперь это не так.

Просто следуйте руководству cgo и используйте C.CString. Если вы боретесь за эффективность, вы выиграете гораздо больше, просто не используя cgo, потому что накладные расходы на вызов C намного больше, чем на выделение памяти и копирование строки.

person Art    schedule 27.02.2017
comment
Относительно вашего последнего утверждения - накладные расходы на вызов C намного больше, чем выделение некоторой памяти и копирование строки - есть ли у вас какие-либо тесты для резервного копирования? - person Not_a_Golfer; 27.02.2017
comment
@Not_a_Golfer На самом деле знаю. Год назад: github.com/art4711/cgo_overhead Если у меня будет время, я обновлю его до 1.8. - person Art; 27.02.2017
comment
Обновлено для 1.8. В версии 1.8 вызов функции cgo выполняется всего в 36 раз медленнее, чем в 92 раза, по сравнению с вызовом функции Go. - person Art; 27.02.2017
comment
Иисус! Я не знал, что это так дорого. что вызывает это? - person Not_a_Golfer; 27.02.2017
comment
@Not_a_Golfer Много чего. Нужно изменить стек, многие из нормальных функций, которые эта функция не использует, оптимизации стека отключены, запускается куча вещей, чтобы убедиться, что мы не нарушаем правила сборщика мусора (даже когда функция C не принимает аргументов) , так далее. - person Art; 27.02.2017