博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang调用c++的dll库文件
阅读量:5172 次
发布时间:2019-06-13

本文共 2812 字,大约阅读时间需要 9 分钟。

最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记: 一、DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll, Com组件dll:不管是何种语言写的都可以调用,但com分很多种。比如而php只能调用com的dll的特定的几种、不能直接调用动态dll,要使用或者编译来迂回调用 动态dll:只要遵循约定的 DLL 接口规范和调用方式,用各种语言编写的 DLL 都可以相互调用。譬如 Windows 提供的系统 DLL (其中包括了 Windows 的 API ),在任何开发环境中都能被调用,不在乎其是 Visual Basic 、 Visual C++ 还是 Delphi
二、动态dll文件里面需要被其他程序访问的函数必须导出,有2种方法(c++,其他语言不清楚) 源文件如下: DllTestDef.h
#ifndef DLLTESTDEF_H#define DLLTESTDEF_H    int  add(int x, int y);#endif
DllTestDef.cpp
#include "DllTestDef.h"int  add(int x, int y){    return x + y;}
2.1、通过在.h头文件里面为函数添加 __declspec(dllexport),例如:
_declspec(dllexport) int add(int a, int b);
说明:此方式下,如果调用该dll的是一个c++程序(同一个编译器的版本)是没有问题的。但是如果是一个其它语言的程序(如C#、VB),则会出错
因为VC++编译器对于__declspec(dllexport)声明的函数会进行名称转换,如上面的函数会转换为Add@0,这样你在VB中必须这样声明:
Declare Function Add Lib "DLLTestDef.dll" Alias "Add@0" () As Long
@后面的数由于参数类型不同而可能不同。这显然不太方便。
为了解决这一问题,我们往往在函数前面再加一个extern "C",使用C方式的函数命名规则。所以为了大范围的使用我们基本申明都如下:
extern "C" _declspec(dllexport) int add(int a, int b);
DllTestDef.h
#ifndef DLLTESTDEF_H#define DLLTESTDEF_H    extern "C"  __declspec(dllexport) int  add(int x, int y);#endif
DllTestDef.cpp同源文件
2.2、使用.def文件,为了简化2.1的那一长串代码,MS引入了def文件方便我们操作。
DllTestDef.h同源文件
DllTestDef.cpp同源文件
DllTestDef.def
LIBRARY DllTestDefEXPORTSadd @ 1;导出其中的add函数,并指定add函数的序号为1;sub @ 2

添加文件到项目属性里面的Linker/input里面

三、在golang里面使用动态dll,也有3种方法 注意的是golang由于数据类型和c++的不一致,在需要传参的时候需要把所有的参数都转换成uintptr指针类型,而且转换的过程需要借助unsafe.Pointer指针
package mainimport (    "fmt"    "syscall"    "unsafe")func IntPtr(n int) uintptr {    return uintptr(n)}func StrPtr(s string) uintptr {    return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))}func Lib_add(a, b int) {    lib := syscall.NewLazyDLL("lib.dll")    fmt.Println("dll:", lib.Name)    add := lib.NewProc("add")    fmt.Println("+++++++NewProc:", add, "+++++++")    ret, _, err := add.Call(IntPtr(a), IntPtr(b))    if err != nil {        fmt.Println("lib.dll运算结果为:", ret)    }}func DllTestDef_add(a, b int) {    DllTestDef, _ := syscall.LoadLibrary("DllTestDef.dll")    fmt.Println("+++++++syscall.LoadLibrary:", DllTestDef, "+++++++")    defer syscall.FreeLibrary(DllTestDef)    add, err := syscall.GetProcAddress(DllTestDef, "add")    fmt.Println("GetProcAddress", add)    ret, _, err := syscall.Syscall(add,        2,        IntPtr(a),        IntPtr(b),        0)    if err != nil {        fmt.Println("DllTestDef.dll运算结果为:", ret)    }}func DllTestDef_add2(a, b int) {    DllTestDef := syscall.MustLoadDLL("DllTestDef.dll")    add := DllTestDef.MustFindProc("add")    fmt.Println("+++++++MustFindProc:", add, "+++++++")    ret, _, err := add.Call(IntPtr(a), IntPtr(b))    if err != nil {        fmt.Println("DllTestDef的运算结果为:", ret)    }}func main() {    Lib_add(4, 5)    DllTestDef_add(4, 5)    DllTestDef_add2(4, 5)}

转载于:https://www.cnblogs.com/lxsky/p/5203940.html

你可能感兴趣的文章
平衡二叉树(AVL Tree)
查看>>
【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
查看>>
【CF799E】Aquarium decoration 线段树
查看>>
大运飞天 鲲鹏展翅
查看>>
从ECMA到W3C
查看>>
软件工程--第十六周学习进度
查看>>
yii2 ActiveRecord多表关联以及多表关联搜索的实现
查看>>
搜狗输入法安装--ubuntu
查看>>
ps/2接口键盘的输入及显示
查看>>
Swift———a Glance(极客学院)笔记
查看>>
【poj3294-不小于k个字符串中最长公共子串】后缀数组
查看>>
java如何获取其它用户登录的真是IP地址
查看>>
Jquery通过指定层次关系获取元素
查看>>
c# for 和 foreach 的区别
查看>>
docfx (一)
查看>>
HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
查看>>
深度学习之前馈神经网络(前向传播和误差反向传播)
查看>>
IEnumerable<T>和IQueryable<T>区别
查看>>
(转)MFC界面风格
查看>>
Centos7 tmux1.6 安装
查看>>