• calling c++ from golang with swig--windows dll (四)


    calling c++ from golang with swig--windows dll 四

    前面讲述了windows环境下golang如何通过swig调用C++ dll。由于编译c++代码使用了gcc,需要为DLL文件增加按照g++ name mangling的导出项。如果DLL导出了大量函数、类或变量,为DLL编写def文件是一项非常麻烦、无聊的事情。如果golang能够利用visual c++编译器来编译c++代码的话,或许不需要额外的def文件了,但是我用百度和谷歌浏览器进行了大量的搜索,没有找到相关的内容,即使是关于golang如何调用c++ DLLload-time dynamic linking)的相关内容也没有。

    为此,需要一个工具来自动生成def文件。这个工具解析DLL文件,利用一些工具和windows api来自动生成def文件,利用def文件再次编译DLL文件。编译后的DLL既可以被Golang调用也可以被C++调用。下面讲一下实现思路。

    第一步需要按照PE规范来解析DLL,找到DLL的导出函数列表。实现这步有多种方法,可以用dumpbin  /EXPORT Simple.dll, 从命令输出的内容可以找到导出内容;golang "debug/pe"包提供了pe解析功能,很容易获取导入符号,要获取DLL的导出项还需要在该包的基础上继续解析PE;还可以利用github上的开源pe解析库,其中的一个 (https://github.com/trailofbits/pe-parse),IterExpVA以回掉函数的形式返回导出项。在我实现的工具中就使用了这个开源pe库。

    第二步,将第一步返回的导出符号列表进行unmangling,得到函数的原始名称。同样有多种方法。可以用undname.exe,解析其输出内容。最好的方法是调用windows apiUnDecorateSymbolName提供了将decorated name还原到函数签名的功能,并且有很多可选项。

    第三步,根据UnDecorateSymbolName得到的结果,推导函数或变量的签名,并给函数一个简单的实现,只提供{}即可。好在微软提供了这个api,否则比较难实现这个自动化工具。分别传入

    UNDNAME_COMPLETEUNDNAME_NAME_ONLY、(UNDNAME_NO_MS_KEYWORDS|undname2.UNDNAME_NO_ACCESS_SPECIFIERS),根据三次输出的结果即可推导。例如 CSimple::CSimple构造函数,

    class CSimple{

            CSimple(void);

            };

    CSimple::CSimple(void){}

    第四步,对上步推导出的函数进行g++ name mangling,没有单独的工具能够做这件事情。只能借助g++预处理结果来找到mangled name。调用命令g++ -x c++ -S in.cpp -o out.txt

    输出文件内容中,.globl对应mangled name。注意一个函数可能有多个导出,例如构造函数会有两个。

        按照上面的思路去做,就可以创建这样一个自动化工具。

        

  • 相关阅读:
    转:C/C++基本数据类型所占字节数
    转:为什么C++中空类和空结构体大小为1?
    转:内存字节对齐
    转:100层楼扔两个鸡蛋的问题
    移动互联网
    辗转相除法
    斐波那契数列
    error C2783: 无法为“T”推导 模板 参数
    创新工场和海豚浏览器宣讲会启示
    转:快速排序的一个小问题没想明白,求助各位
  • 原文地址:https://www.cnblogs.com/majianguo/p/6684846.html
Copyright © 2020-2023  润新知