zoukankan      html  css  js  c++  java
  • DLL导出的方式

    DLL导出的方式

    1. 调用约定

    _CDECL: c语言的默认调用形式,也是C++的默认调用形式
    特点:参数从右到左入栈,调用者负责手动清理堆栈,所以传入多少参数给被调函数都不会产生编译阶段错误。
    命令行参数:/Gd 开关
    场景:可变参数函数,必须是这种调用方式。
    缺点:每次调用都需要编译器产生清除堆栈的代码。所以比_stdcall方式编译的程序体积大。
    修饰方法: 对于C函数,默认是函数名前加一个下划线。对于C++函数,使用EXTERN “C” 修饰后也是加下划线,若不加EXTERN “C,有特别复杂的方式。

    _STDCALL: Pascal程序默认调用方式,大多数WINDOWS API也是这种调用约定。俗称:C++标准调用约定。
    特点: 参数也是从右到左入栈,由被调函数自己清理堆栈。如果有类成员,最后一个入栈的是this指针,CPU指令是retn X ,X是参数占用的字节数。
    所以函数在编译时就确定参数的个数,不能多也不能少,否则返回时会出错。
    命令行参数:/Gz 开关
    场景:windows API都是,windows中回调函数必须是_stdcall方式。
    缺点:—
    修饰方法:对于C函数,下滑线开头,函数名+@+参数字节数 比如_function@number

    2.DLL导出函数名修饰

    C++为了函数重载,把函数名修饰方法做成这样:
    ?fnfunctionname@@YGHXZ (@@YG是_stdcall方式,@@YA是_cdecl方式,H代表返回值类型int,X是参数void,Z是结束符)
    ?fnfunctionname@@YGXH@Z (@@YG是_stdcall方式,@@YA是_cdecl方式,X代表返回值类型void,H是参数int,@Z是结束符) 所以无参数时以@Z结尾。

    C++这么恶心的修饰方法是为了重载函数,导出的名字太乱,调用方无法正确用名字找到函数。所以需要加上EXTERN “C” 修饰,以C语言的方式编译,导出特定修饰的函数名。

    3.DLL函数导出的2中方式

    A.__declspec(dllexport)导出函数的方式:有隐式调用的便利(给一个dll函数导出表lib文件和头文件就行了),def文件却没有,所以def逐渐已经久远了。

    B.def文件导出函数,导出名不被修改。但是不支持c++重载的,重载的函数名一样。。。。 可以在函数名后加 空格+@number 表示导出序号,利于调用时找到函数。导出变量: 变量名+ DATA字段

    4.历史是:

    1.C++编译器为了重载,会把函数名字修饰的很复杂,参数类型,返回类型…都在函数名修饰中体现。
    2.为了C++继续使用大量的c语言编写的库,C++使用 EXTERN”C”包含C代码的策略。所以一般C++语言函数要加EXTERN “C” 修饰,使这段代码C方式编译。
    3.C语言是不支持EXTERN “C” 修饰规约的,本身就是c代码,何来外部c代码。

    5.结果是:

    1. 项目是C++编写的DLL,支持隐式调用使用__declspec(dllexport)导出,若明确动态调用,也可以def定义导出。
    2. 为了C++和C混合编程,c++代码加EXTERN “C” ,但是C语言包含使用C++的头文件时,因为C++头文件可能有EXTERN “C”,会错误,只能使用extern void do();声明C++头文件
      中的函数。
    3. 一般windows DLL导出函数需要时_stdcall 约定,脚本语言没法主动清理堆栈。这样导出的函数名尽管有EXTERN”C”修饰,但是为了函数自己清理堆栈,函数名被修饰成
      _functionname@4这样的名字。
    4. 正常是EXTERN”C” + __declspec(dllexport) + _cdecl + 函数:名字不会被修改。(默认的方式,可以不加_cdecl)
      假如 EXTERN”C” + __declspec(dllexport) + _stacall + 函数:名字还是会修改成_functionname@4这样的。这时可以加个def文件,也可以在代码中加入如下语句:

    5. #pragma comment(linker,”/EXPORT:TransportInit=_TransportInit@8”) 预编译指定导出函数名不变,不过这样__declspec(dllexport)也会导出一遍被修饰的。dll中是这样的

      TransportInit(00000293)
      _TransportInit@8(00000293)

  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/hystill/p/13783214.html
Copyright © 2011-2022 走看看