正确更改* C.char的正确方法

时间:2018-11-02 14:41:17

标签: go cgo

我是go和cgo的新手,在浏览了一段时间的互联网之后,我还没有想出一种从go更改char *的好方法。

从go更改* C.char的最快方法是什么

这是我的代码,也是我尝试更改字符串的方法(无效)

package asciiEngine

// #include <windows.h>
import "C"

type Screen struct {
    Width, Height int
    Length        C.ulong
    Data          *C.char
    GoData        string
    HConsole      C.HANDLE
    BytesWritten  C.DWORD
    Start         C.COORD
}

func (s Screen) Draw() {
    C.WriteConsoleOutputCharacter(s.HConsole, s.Data, s.Length, s.Start, &s.BytesWritten)
}

func CreateScreen(width, height int) Screen {
    screen := Screen{
        Width:        width,
        Height:       height,
        Length:       C.ulong(width * height),
        Data:         (*C.char)(C.malloc(C.ulonglong(width * height))),
        HConsole:     C.CreateConsoleScreenBuffer(C.GENERIC_READ|C.GENERIC_WRITE, 0, nil, C.CONSOLE_TEXTMODE_BUFFER, nil),
        BytesWritten: 0,
    }
    screen.GoData = C.GoString(screen.Data) // my attempt to get a reference to the C string
    //C.SetConsoleActiveScreenBuffer(screen.HConsole)
    return screen
}

main.go:

package main

// #include "stdio.h"
// void print(char* data) {
//  printf(data);
// }
import "C"

import (
    "fmt"

    "github.com/demantar/ascii-engine"
)

func main() {
    screen := asciiEngine.CreateScreen(100, 50)
    C.print((*C.char)(screen.Data))
    fmt.Println()
    screen.GoData = "askdssdfselkkskdkflsekfjdkjfksjeflsdkfjjekdjflskasdfkksdjjekdskdfjkskd"
    C.print((*C.char)(screen.Data))
}

输出

P

P

我对C语言也很陌生,之所以这样做是因为我找不到可以做到这一点的库

1 个答案:

答案 0 :(得分:2)

例如,将gData用作对基础byte C cData数组的Go char切片引用。

package main

import (
    "fmt"
    "unsafe"
)

/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int printData(unsigned char *data) {
    return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data);
}
*/
import "C"

func main() {
    // Allocate C data buffer.
    width, height := 8, 2
    lenData := width * height
    // add string terminating null byte
    cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar))

    // When no longer in use, free C allocations.
    defer C.free(unsafe.Pointer(cData))

    // Go slice reference to C data buffer,
    // minus string terminating null byte
    gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData]

    // Write and read cData via gData.
    for i := range gData {
        gData[i] = '.'
    }
    copy(gData[0:], "Data")
    gData[len(gData)-1] = 'X'
    fmt.Printf("gData: %d %q\n", len(gData), gData)
    C.printData(cData)
}

输出:

gData: 16 "Data...........X"
cData: 16 "Data...........X"

参考:Command cgo