GO语言调用DLL,填平所有的坑,最详尽攻略

2024-05-07 10:08

本文主要是介绍GO语言调用DLL,填平所有的坑,最详尽攻略,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

由于业务需要,购买了别人写好的一个DLL模块,于是磨难开始了,经历多天的折磨,终于完美解决。

首先DLL如果是32位的,编译前运行 

set GOARCH=386

第一个DLL函数,第一个参数,要求传入一个指针,直接指向[]byte类型,注意,是直接指向;第2个参数为[]byte长度;第三个参数为一个直接指向string类型指针;返回一个整数,标识调用成功或失败。

最折磨我的就是直接指向某种类型的指针传递问题,查了N多资料,都是类似下面这样:

p:= unsafe.Pointer(&dat)
g:=dll32.NewProc("XXX")
r, _, _ :=g.Call(uintptr(p),uintptr(cdat),uintptr(pk))
我开始也这样用,怎么弄都不对,然后我用OD载入调试,发现传进去的东西根本不是DLL想要的。

这样传进去的数据会被2层指针指向,ptrA->ptrB->[]byte,传进去的是ptrA,所以导致无法正常调用。那么问题来了,怎么才能传进去的指针直接指向数据,达到类似ptrA->[]byte这样的效果呢?

问题的重点就在这里,研究了好几天uintptr发现不是它的问题,问题出在

unsafe.Pointer

它上面,它会在指针外面再包一层指针,怎么解决呢?我只能考虑先把指针转成整数再传进去,结果

p:= *((*int32)(unsafe.Pointer(&dat)))
r, _, _ :=g.Call(uintptr(p),uintptr(cdat),uintptr(pk))
这样成功了。下面传递整数指针就简单多了

cdat:=len(dat)
这样即可,再后面传递字符串指针,指针获取方式和byte一样即可。但是问题又来了,执行不成功,继续OD,发现有问题,问题在于GO语言字符串后面在内存中没有结尾标志。那GO自己怎么判断字符串结尾呢?我想应该是每个字符串GO都同时记录了长度吧,不过不确定,有明白的大神请告知,这个问题我就只能这样,先把字符串转换成byte,然后在byte最后加0,类似这样

keystr:=[]byte{49,50,51,0}
pk:= *((*int32)(unsafe.Pointer(&keystr)))
这个问题就解决了,这个字符串就变成windows识别的了。返回值整数,直接就能用,这点我很奇怪,不知道为什么,比如这里,可以直接

r, _, _ =g.Call(uintptr(p),uintptr(cdat),uintptr(pk))
if r!=1 {
按理说,返回的是个指向整数的指针,应该*r才对,不懂,大神告知。

然后现在所有传递参数的问题解决了,后面问题又来了,第2个函数,调用后返回值是指向字符串的指针,这个指针指向的内容字符串当然是0结尾的windows格式了,GO依然无法正确读取。怎么办呢,只能自己写了个函数处理这个问题

//根据DLL返回的指针,逐个取出字节,到0字节时判断为字符串结尾,返回字节数组转成的字符串
func prttostr(vcode uintptr) string {var vbyte []byte
   for i:=0;i<10;i++{sbyte:=*((*byte)(unsafe.Pointer(vcode)))if sbyte==0{break
      }vbyte=append(vbyte,sbyte)vcode += 1
   }return string(vbyte)
}
原理就是操作指针一直向后移动,发现0了就停止,这样问题解决了,虽然所有的资料和大神都告诉我,不要轻易操作指针,但是这种情况下,不这么弄,怎么弄呢?谁能告诉我。

无论如何问题终于解决了,也许解决的不够完美,我想应该有更简单的办法,但是我不知道。


这篇关于GO语言调用DLL,填平所有的坑,最详尽攻略的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967050

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

mss32.dll文件丢失怎么办? 电脑提示mss32.dll丢失的多种修复方法

《mss32.dll文件丢失怎么办?电脑提示mss32.dll丢失的多种修复方法》最近,很多电脑用户可能遇到了mss32.dll文件丢失的问题,导致一些应用程序无法正常启动,那么,如何修复这个问题呢... 在电脑常年累月的使用过程中,偶尔会遇到一些问题令人头疼。像是某个程序尝试运行时,系统突然弹出一个错误提

电脑提示找不到openal32.dll文件怎么办? openal32.dll丢失完美修复方法

《电脑提示找不到openal32.dll文件怎么办?openal32.dll丢失完美修复方法》openal32.dll是一种重要的系统文件,当它丢失时,会给我们的电脑带来很大的困扰,很多人都曾经遇到... 在使用电脑过程中,我们常常会遇到一些.dll文件丢失的问题,而openal32.dll的丢失是其中比较

电脑win32spl.dll文件丢失咋办? win32spl.dll丢失无法连接打印机修复技巧

《电脑win32spl.dll文件丢失咋办?win32spl.dll丢失无法连接打印机修复技巧》电脑突然提示win32spl.dll文件丢失,打印机死活连不上,今天就来给大家详细讲解一下这个问题的解... 不知道大家在使用电脑的时候是否遇到过关于win32spl.dll文件丢失的问题,win32spl.dl

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时