Golang调用C函数-返回字符串

2023-02-23

golang仅支持c函数调用

C函数实例

目录结构

.
├── CMakeLists.txt
├── includes
│   └── library.h
└── src
    └── library.cpp

源码

library.h

#ifndef PDVCLIBRARY
#define PDVCLIBRARY

#ifdef __cplusplus
extern "C"{
#endif

extern int testFunc();

extern char *testString();

#ifdef __cplusplus
}
#endif

#endif

library.cpp

#include "library.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>


int testFunc()
{
    unsigned int sum = 0;
    for (size_t i = 0; i < 100; i++)
    {
        for (size_t j = 0; j < 100; j++)
        {
            for (size_t k = 0; k  < 1000000; k++)
            {
                sum += k;
            }            
        }           
    }
    return sum;    
}

char *testString()
{
    char *str = (char *)malloc(13*sizeof(char));
    sprintf(str,"%s","Hello world!");
    return str;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(CLibiary VERSION 0.1 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 11)


include_directories(
    ./includes/
)

FILE(GLOB CLibiary_Header "./includes/*.h")
FILE(GLOB CLibiary_SRC "./src/*.cpp")

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build/libs/$<0:>")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build/bin/$<0:>")

#静态库
set(CLibiary_Target_STATIC "CLibiarySTATIC")
add_library(${CLibiary_Target_STATIC} STATIC  ${CLibiary_Header} ${CLibiary_SRC})
target_link_libraries(${CLibiary_Target_STATIC} -Wall -pthread)

#动态库
set(CLibiary_Target_SHARE "CLibiarySHARED")
add_library(${CLibiary_Target_SHARE} SHARED  ${CLibiary_Header} ${CLibiary_SRC})
target_link_libraries(${CLibiary_Target_SHARE} -Wall -pthread)


file(COPY ./includes/ DESTINATION ./build/includes/)

静态库(动态库方式见上一篇文章)

目录结构

注释同动态库目录结构

.
├── go.mod
├── libCLibiarySTATIC.a
├── library.h
├── main.go

main.go

package main

/*
#include "library.h"
#include <stdlib.h>
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lCLibiarySTATIC -lstdc++
*/
import "C"
import (
	"fmt"
	"unsafe"
)

func main() {
	//调用C函数
	result := C.testString()
	//result为地址,需要通过C.GoString()转换为golang string
	str := C.GoString(result)
	//释放内存
	C.free(unsafe.Pointer(result))
	fmt.Println(str)
}