Reputation: 24719
I have C struct:
struct sanlk_lockspace {
char name[48];
}
and go-code:
/*
#include ....
*/
import "C"
func main() {
ls := C.struct_sanlk_lockspace{name: C.CString("lockspace_11")}
}
As result, I see error:
cannot use _Cfunc_CString("lockspace_11") (type *_Ctype_char)
as type [48]_Ctype_char in field value
How to convert the string type correctly? ?
Upvotes: 1
Views: 225
Reputation: 785
In short, it's not working because [48]_Ctype_char is a very different structure than *_Ctype_char.
In Go, an array is quite different from most other languages. An array in Go is more like a struct with numeric property identifiers. In C, an array is a pointer to a specific type, but where it is known to the developer that additional instances of that type are in contiguous memory after the 0th element. In Go, a string is a struct with two attributes, Data
and Len
. The Data
attribute is more like what C knows as an array or string. The Len
attribute is the number of contiguous instances of the unit-type.
The trouble you're having is that a struct of 48 fields, all c::char, is not assignable with a pointer to an instance of c::char. The fact that 47 allocations exist contiguous with that single instance is something you as the developer know, but it is a fact concerning which the Go compiler is quite unconvinced.
The simplest cast you could do would be to declare a specific type as a struct with {Data *_Ctype_char; Len uintptr}
, and assign the value with Data as the literal result, and Len is the number of instances of _Ctype_char values that can be read before encountering _Ctype_char(0)
.
To convert that to a string, you would have to convert the single-byte _Ctype_Char to a multi-byte unicode character, of Go-type glyph
for each element of that sequence.
At the point that you have a Go instance of a struct with a pointer to glyph and a uintptr sized number, it can be converted to a Go-type String. The reverse would be to convert each contiguous glyph back to its uint8 correlative, if one exists, optionally implementing some strategy to losslessly convert, and cap it with a uint8(0)
if the original was not preserved. That *uint8, which the compiler now has no record as to size, is compatible with *_Ctype_char, and can be written back to a C-type string.
Upvotes: 3