Go调用C语言

olivee 5年前 ⋅ 1080 阅读

1. 两种集成方式方式

1.1 代码集成

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

char** getStringArray(){
	char** list = malloc(sizeof(char*));
	list[0] = "xing";
	list[1] = "jack";
	list[2] = "john";
	return list;
}

void showStringArray(char** list){
	int num = strlen(*list)-1;
	int i = 0;
	for(i=0;i<num;i++){
		printf("%s\n",list[i]);
	}
}

*/
import "C"

1.2 库函数集成

/*
#cgo CFLAGS: -Iinclude

#cgo LDFLAGS: -Llib -llibSmCrypto-x64

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

其中:

  • CFLAGS中的-Iinclude指定SmCryptoUtil.h所在的路径为include(可以用相对路径也可以用绝对路径,这里用的是相对路径)

  • LDFLAGS中的-Llib指定libSmCrypto-x64.dll所在的路径为lib,-llibSmCrypto-x64指定dll的文件为libSmCrypto-x64.dll

  • include "SmCryptoUtil.h"指定引入头文件SmCryptoUtil.h

2. 类型转换

2.1 go与C语言中的int和*char类型转换

package main

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

typedef struct {
	unsigned char *data;
	size_t length;
} sm_data_t;

unsigned char * test(unsigned char *inData,unsigned char *outData) {
	printf("--C --parameter inData is:%s\n", inData);
	unsigned char *data;
	data = (unsigned char *)strdup("xxx123");

	outData[0]= 'x';
	outData[1]= '1';
	outData[2]= '2';
	outData[3]= '2';
    return data;
}

int Connect(char * cHostIp,int *port,int timeout){
	return 100;
}
*/
import "C"

import (
	"fmt"
	"unsafe"
)

func reversByte(data []byte) []byte {
	dataLen := len(data)
	var result = make([]byte, dataLen)
	for i,b := range data {
		result[i] = ^b
	}
	return result[:dataLen]
}

func testint(a int){

}

func main() {
	addr := "127.0.0.1"
	port := 8080
	// 字符串和*int参数传入,返回C.int类型
	r := C.Connect(C.CString(addr),(*C.int)(unsafe.Pointer(&port)),1)
	// C.int转换go int结果
	rCode := int(r)
	fmt.Printf("==go==int result is:%v\n", r)
	fmt.Printf("==go==int result is:%v\n", rCode)

	in := []byte("Hello")
	var out = make([]byte, 10)
	// *char参数传入,返回*char类型
	result := C.test((*C.uchar)(&in[0]), (*C.uchar)(&out[0]))
	r2 := (*C.char)(unsafe.Pointer(result))
	outStr := string(out)
	// *char转换string结果
	resultStr := C.GoString(r2)

	fmt.Printf("==go==param out:%v\n", outStr)
	fmt.Printf("==go==result address is:%v,value is:%v\n",result, resultStr)
}

2.2 go与c字符串数组互转

package main

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

char** getStringArray(){
	char** list = malloc(sizeof(char*));
	list[0] = "xing";
	list[1] = "jack";
	list[2] = "john";
	return list;
}

void showStringArray(char** list){
	int num = strlen(*list)-1;
	int i = 0;
	for(i=0;i<num;i++){
		printf("%s\n",list[i]);
	}
}

*/
import "C"

import (
	"fmt"
	"unsafe"
	"reflect"
)

func main(){
	//char** 转化成 []string
	list := C.getStringArray()
	var str []string
	var pbuf []*C.char
	header := (*reflect.SliceHeader)(unsafe.Pointer(&pbuf))
	header.Cap = 3
	header.Len = 3
	header.Data = uintptr(unsafe.Pointer(list))
	for _,i := range pbuf {
		str = append(str, C.GoString(i))
	}
	fmt.Println(str)

	//[]string 转化成 char**
	box := []string{"xing","jack","john"}
	var buf []*C.char
	for i,_ := range box {
		buf = append(buf, (*C.char)(unsafe.Pointer(C.CString(box[i]))))
	}
	box2 := (**C.char)(unsafe.Pointer(&buf[0]))
	C.showStringArray(box2)

}

2.3 C语言中的结构体引用及转换

package main

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

typedef struct {
	unsigned char *data;
	size_t length;
} str_data_t;

const str_data_t structDataTest(const str_data_t indata){
	str_data_t stu1;
	stu1.data = "5678";
	stu1.length = 4;
	return stu1;
}
*/
import "C"

import (
	"fmt"
	"unsafe"
)


func main() {
	content := "1234"
	var strdata C.str_data_t
	strdata.data =(*C.uchar)(unsafe.Pointer(&content))
	strdata.length = 4

	b := C.structDataTest(strdata)

	r2 := (*C.char)(unsafe.Pointer(b.data))
	d := C.GoString(r2)

	fmt.Printf("struct resunt data is:%v\n", d)

}