2013-07-26 2 views
3

в главном корпусе у меня есть:golang: Могу ли я разделить C.int между пакетами

var foo C.int 
foo = 3 
t := fastergo.Ctuner_new() 
fastergo.Ctuner_register_parameter(t, &foo, 0, 100, 1) 

в пакете fastergo я есть:

func Ctuner_register_parameter(tuner unsafe.Pointer, parameter *C.int, from C.int, to C.int, step C.int) C.int { 
    ... 
} 

если я пытаюсь запустить его, я получаю :

demo.go:14[/tmp/go-build742221968/command-line-arguments/_obj/demo.cgo1.go:21]: cannot use &foo (type *_Ctype_int) as type *fastergo._Ctype_int in function argument 

я не совсем уверен, что идти пытается сказать мне здесь, но почему-то я думаю, что он хочет сказать мне, что все C.int не равны? Почему это так? как я могу решить эту проблему?

+0

Эти два типа как-то кажутся разными (_Ctype_int и fastgo._Ctype_int). Я точно не знаю, как работает cgo, но откуда берется C.int? Это из какого-то импортированного пакета? –

+0

@Laurent "C" - это псевдопакет для использования кода C в go. Читайте: http://golang.org/doc/articles/c_go_cgo.html в основном я имею в виду один и тот же тип (целое число на C) дважды, и Go не видит их как эквивалентные. – mnagel

+0

Попробуйте определить '_Ctype_int' в пакете' fastgo', а затем последовательно ссылайтесь на него как 'fastgo._Ctype_int'. В настоящее время они находятся в разных областях. – Intermernet

ответ

4

Поскольку _Ctype_int не начинается с буквы в верхнем регистре Юникода, тип является локальным для пакета. Используйте типы Go, за исключением пакета C wrapper, где вы конвертируете их в типы C. Пакет обертки должен скрывать все детали реализации.

Вы не предоставляете нам достаточной информации для создания образца кода, который компилируется и запускается. Вот приблизительная схема того, что я ожидал увидеть:

package main 

import "tuner" 

func main() { 
    var foo int 
    foo = 3 
    t := tuner.New() 
    t.RegisterParameter(&foo, 0, 100, 1) 
} 

.

package tuner 

import (
    "unsafe" 
) 

/* 
#include "ctuner.h" 
*/ 
import "C" 

type Tuner struct { 
    ctuner uintptr 
} 

func New() *Tuner { 
    var t Tuner 
    t.ctuner = uintptr(unsafe.Pointer(C.ctuner_new())) 
    return &t 
} 

func (t *Tuner) RegisterParameter(parameter *int, from, to, step int) error { 
    var rv C.int 
    rv = C.ctuner_register_parameter(
     (*C.ctuner)(unsafe.Pointer(t.ctuner)), 
     (*C.int)(unsafe.Pointer(parameter)), 
     C.int(from), 
     C.int(to), 
     C.int(step), 
    ) 
    if rv != 0 { 
     // handle error 
    } 
    return nil 
} 
+0

Благодарим за отличную обратную связь, но позвольте мне проверить: 'C' преобразует типы C в локальные типы пакетов Go (обозначается ведущим' _'), и они по своей сути несовместимы с типами из других пакетов - даже для базовых типов как 'C.int'. Решение состоит в том, чтобы как можно скорее преобразовать в типы Go и использовать типы Go (совместимые с границами пакетов) везде. Для этого требуется написать несколько чистую упаковку. Если бы мне захотелось быстро и грязно, я мог бы скопировать и вставить все из «тюнера» в «main» (стиль спагетти), и все будет работать так же ... – mnagel

+0

забыл упомянуть ваше имя, @peterSO – mnagel

+0

@peterSO: Поскольку 'ctuner uintptr' имеет строчные буквы (например, не экспортируется), в чем причина не объявлять его как 'ctuner * C.ctuner'? – dmajkic