go如何调用C动态库函数

 更新时间:2025年05月23日 08:39:06   作者:码灵  
这篇文章主要介绍了go如何调用C动态库函数的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

go调用C动态库函数

方式一

  • 直接调用动态库,需要有头文件;
  • 没有的话还需要自己再写一个动态库去调用;
  • 过程比较繁琐;

方式二

  • 直接使用cgo调用;
  • 使用dlopen去调用动态库;
  • 比较方便和go代码在一个文件上;

1 字符串、int相互转换;

2内存手动释放;

!!! go 调用C动态库不支持交叉编译!

package main


/*
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#cgo LDFLAGS: -ldl

struct Hardware_API_Result {
   int  result;
   char json[256];
};


char* getSysTime(){
   //  手动加载指定位置的so动态库
	void* handle = dlopen("libhardwareInfo2.so", RTLD_LAZY);
	struct Hardware_API_Result (*getSysT)();

	//根据动态链接库操作句柄与符号,返回符号对应的地址
	getSysT = dlsym(handle, "get_system_time");

	//struct MidStruct midres;
	struct Hardware_API_Result r;
	r = getSysT();

	//static char* cj="404";  不能使用静态变量,多个线程调用,值会覆盖;测试:多次调用go中日志输出成乱码
	char * cj;
	cj = (char *)malloc(256);
	strcpy(cj,"404");
	//
	if(r.result==0){
	   strcpy(cj,r.json);
	}
	dlclose(handle);
	return cj;
}
int start4G(){
	void* handle = dlopen("libhardwareInfo2.so", RTLD_LAZY);
	int (*start4G)();
	start4G = dlsym(handle, "start_4g");
	int rv=start4G();
	dlclose(handle);
	return rv;
}

int ping(char* cip){
    void* handle = dlopen("libhardwareInfo2.so", RTLD_LAZY);
	struct Hardware_API_Result (*midFuncName)( char* );
    midFuncName = dlsym(handle, "ping");
	struct Hardware_API_Result midres;
    midres=midFuncName(cip);
	int rvi=midres.result;
    dlclose(handle);

    return rvi;
}


*/
import "C"
import (
	"fmt"
	"unsafe"
)


/*
获取系统时间
json 格式:{"local_time":2020-03-23  03:02:46.795268}
*/
func getSystime() string {
    //c中指针
	sip:=C.getSysTime()
	//转变为go字符串
	si:=C.GoString(sip)
	//释放c中指针
	C.free(unsafe.Pointer(sip))
	return  si
}
/*
启动4g,启动成功返回0
*/
func start4G() int{
	//c类型
	mrv:=C.start4G()
	//转换成go int类型
	rv:=int(mrv)
	return rv
}


/**
判断某ip可否ping通,值为0表示通
*/
func ping(ip string)int{
	cip := C.CString(ip)
	mrv:=C.ping(cip)
	rv:=int(mrv)
	C.free(unsafe.Pointer(cip))
	return rv
}

参考方法1

C.char  
C.schar (signed char)  
C.uchar (unsigned char)  
C.short  
C.ushort (unsigned short)  
C.int  
C.uint (unsigned int)  
C.long  
C.ulong (unsigned long)  
C.longlong (long long)  
C.ulonglong (unsigned long long)  
C.float  
C.double.   
  
  
unsafe.Pointer (void*)  
  
// Go string to C string  
func C.CString(string) *C.char  
  
var val []byte  
(*C.char)(unsafe.Pointer(&val[0]))

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 简单聊聊Golang中defer预计算参数

    简单聊聊Golang中defer预计算参数

    在golang当中defer代码块会在函数调用链表中增加一个函数调用,下面这篇文章主要给大家介绍了关于Golang中defer预计算参数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • RabbitMq如何做到消息的可靠性投递

    RabbitMq如何做到消息的可靠性投递

    现在的一些互联网项目或者是高并发的项目中很少有没有引入消息队列的。 引入消息队列可以给这个项目带来很多的好处,这篇文章主要为大家介绍了RabbitMq如何做到消息的可靠性投递,有需要的朋友可以借鉴参考下
    2022-12-12
  • golang 实现 pdf 转高清晰度 jpeg的处理方法

    golang 实现 pdf 转高清晰度 jpeg的处理方法

    这篇文章主要介绍了golang 实现 pdf 转高清晰度 jpeg,下面主要介绍Golang 代码使用方法及Golang PDF转JPEG的详细代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • Golang高效解析和生成XML的示例详解

    Golang高效解析和生成XML的示例详解

    这篇文章将从Golang中处理XML的基本概念开始,详细介绍如何读取和解析XML文件,然后转向如何创建和输出XML数据,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • Go语言学习之映射(map)的用法详解

    Go语言学习之映射(map)的用法详解

    Map是一种无序的键值对的集合。这篇文章主要为大家详细介绍了Go语言中映射的用法,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
    2022-04-04
  • Go方法接收者值接收者与指针接收者详解

    Go方法接收者值接收者与指针接收者详解

    这篇文章主要为大家介绍了Go方法接收者值接收者与指针接收者详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Golang 变量申明的三种方式

    Golang 变量申明的三种方式

    这篇文章主要介绍了Golang 变量申明的三种方式,帮助大家更好的理解和学习golang,感兴趣的朋友可以了解下
    2020-08-08
  • Go中跨语言实现传输的方法步骤

    Go中跨语言实现传输的方法步骤

    gRPC是Google开源的高性能RPC框架,基于HTTP/2协议和ProtocolBuffers序列化,支持多语言、流式传输和企业级特性,文章详细介绍了gRPC的接口定义语言、服务定义、消息类型、RPC类型以及服务端和客户端的实现方式,需要的朋友可以参考下
    2026-04-04
  • Golang基于文件魔数判断文件类型的案例代码

    Golang基于文件魔数判断文件类型的案例代码

    这篇文章主要介绍了Golang基于文件魔数判断文件类型,本文介绍了基于文件魔数判断文件类型的方法,主要涉及如何ReadSeek读取文件指定字节内容,然后介绍文件魔数,最后给出示例基于魔数判断文件类型,需要的朋友可以参考下
    2023-02-02
  • golang 如何替换掉字符串里面的换行符\n

    golang 如何替换掉字符串里面的换行符\n

    这篇文章主要介绍了golang 替换掉字符串里面的换行符\n操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03

最新评论