doushishi2415 2018-01-13 15:20 采纳率: 0%
浏览 539

从Golang中的C函数返回字符串

I am trying to a call C function in GO. This works to some extends (for integers). However, there are issues A minimal example is given below

package main

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

void my_reverse(char* src, int len, char *dst){
  dst = malloc(sizeof(char) * (len + 1));
  printf("[c-part] src=%s
", src);
  for (int i = 0; i < len; ++i)
  {
    dst[i] = src[len - 1 - i];
  }
  dst[len] = 0;
  printf("[c-part] dst=%s
", dst);
}

void some_text(char* buffer, unsigned long long int *year){
  buffer = malloc(200 * sizeof(char));
  sscanf("year 2018d", "%s %16llu", buffer, year);
  printf("will return (%s, %16llu)
", buffer, *year);

}
*/
import "C"

import "unsafe"
import "fmt"

func Reverse(a string) (dst string) {

    c_src := C.CString(a)
    defer C.free(unsafe.Pointer(c_src))
    c_len := C.int(len(a))
    c_dst := C.CString(dst)
    defer C.free(unsafe.Pointer(c_dst))

    C.my_reverse(c_src, c_len, c_dst)

    return string(*c_dst)

}

func Sometext() (dst string, year int64) {

    c_dst := C.CString("")
    c_year := C.ulonglong(0)
    defer C.free(unsafe.Pointer(c_dst))

    C.some_text(c_dst, &c_year)

    return string(*c_dst), int64(c_year)

}

func main() {
    fmt.Printf("[gopart] dst=%v


", Reverse("Hello World"))

    buf, year := Sometext()
    fmt.Printf("received (%v, %v)
", buf, year)
}

These are two c-function, which allocate a new buffer in c. However, I get the output

[c-part] src=Hello World
[c-part] dst=dlroW olleH
[gopart] dst=


will return (year,             2018)
received (, 2018)

This means, these strings are available in C.But I can never use these strings in GO afterwards. Does the Go-Garbage collector remove the string before I can use it?

I expect to see

[gopart] dst=dlroW olleH
received (year, 2018)

there as well.

  • 写回答

1条回答

  • douliangbian7323 2018-01-14 02:18
    关注

    You don't need to handle memory allocation in c if you initialize the strings in Go using C.String

    // Go string to C string // The C string is allocated in the C heap using malloc. // It is the caller's responsibility to arrange for it to be // freed, such as by calling C.free (be sure to include stdlib.h // if C.free is needed). func C.CString(string) *C.char

    You can use c.GoString() to convert the C.String back in to go string. Below is a working code snippet of your sample.

    package main
    
    /*
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    void my_reverse(char* src, char *dst){
      printf("[c-part] src=%s
    ", src);
      int n = strlen(src);
      for (int i = 0; i < n ; ++i)
      {
        dst[i] = src[n - 1 - i];
      }
      dst[n] = 0;
      printf("[c-part] dst=%s
    ", dst);
    }
    
    void some_text(char* buffer, unsigned long long int *year){
      sscanf("year 2018d", "%s %16llu", buffer, year);
      printf("will return (%s, %16llu)
    ", buffer, *year);
    }
    */
    import "C"
    
    import "unsafe"
    import "fmt"
    
    func Reverse(a string) (dst string) {
        c_src := C.CString(a)
        defer C.free(unsafe.Pointer(c_src))
        c_dst := C.CString(dst)
        defer C.free(unsafe.Pointer(c_dst))
        C.my_reverse(c_src, c_dst)
        return C.GoString(c_dst)
    }
    
    func Sometext() (dst string, year int64) {
        c_dst := C.CString("")
        c_year := C.ulonglong(0)
        defer C.free(unsafe.Pointer(c_dst))
        C.some_text(c_dst, &c_year)
        return C.GoString(c_dst), int64(c_year)
    }
    
    func main() {
        fmt.Printf("[gopart] dst=%v
    
    
    ", Reverse("Hello World"))
    
        buf, year := Sometext()
        fmt.Printf("received (%v, %v)
    ", buf, year)
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制