stdcall不只是一个调用约定;除了作为调用约定之外,它还允许C和C++对象之间的同构。这里有一个例子:

#define _CRT_SECURE_NO_WARNINGS // disable marking use of strcpy as error.

#include

#include

#include

class ICdeclGreeter {

public:

virtual ~ICdeclGreeter(){}

virtual void setGreeting(const char *greeting) = 0;

virtual void greet() = 0;

};

class IStdcallGreeter {

public:

virtual __stdcall ~IStdcallGreeter(){}

virtual void __stdcall setGreeting(const char *greeting) = 0;

virtual void __stdcall greet() = 0;

};

class CdeclGreeter : public ICdeclGreeter {

public:

char *greeting;

~CdeclGreeter() {

if (greeting != nullptr) {

free(greeting);

puts("[CdeclGreeter] destroyed");

}

}

void setGreeting(const char *greeting) {

this->greeting = (char *)malloc(strlen(greeting) + 1);

strcpy(this->greeting, greeting);

}

void greet() {

puts(greeting);

}

};

class StdcallGreeter : public IStdcallGreeter {

public:

char *greeting;

__stdcall ~StdcallGreeter() {

if (greeting != nullptr) {

free(greeting);

puts("[StdcallGreeter] destroyed");

}

}

void __stdcall setGreeting(const char *greeting) {

this->greeting = (char *)malloc(strlen(greeting) + 1);

strcpy(this->greeting, greeting);

}

void __stdcall greet() {

puts(greeting);

}

};

typedef struct pureC_StdcallGreeter pureC_StdcallGreeter;

typedef struct pureC_StdcallGreeterVtbl {

void (__stdcall *dtor)(pureC_StdcallGreeter *This);

void (__stdcall *setGreeting)(pureC_StdcallGreeter *This, const char *greeting);

void (__stdcall *greet)(pureC_StdcallGreeter *This);

} pureC_IStdcallGreeterVtbl;

struct pureC_StdcallGreeter {

pureC_IStdcallGreeterVtbl *lpVtbl;

char *greeting;

int length;

};

/* naive attempt at porting a c++ class to C;

on x86, thiscall passes This via ecx register rather than

first argument; this register cannot be accessed in C without

inline assembly or calling a reinterpretation of byte array

as a function. there is no "This" argument in any of below. */

typedef struct pureC_CdeclGreeter pureC_CdeclGreeter;

typedef struct pureC_CdeclGreeterVtbl {

void (*dtor)(pureC_CdeclGreeter *This);

void (*setGreeting)(pureC_CdeclGreeter *This, const char *greeting);

void (*greet)(pureC_CdeclGreeter *This);

} pureC_CdeclGreeterVtbl;

struct pureC_CdeclGreeter {

pureC_CdeclGreeterVtbl *lpVtbl;

char *greeting;

int length;

};

void test() {

ICdeclGreeter *g = new CdeclGreeter;

g->setGreeting("hi");

g->greet();

IStdcallGreeter *g2 = new StdcallGreeter;

g2->setGreeting("hi");

g2->greet();

// we can pass pointers to our object to pure C using this interface,

// and it can still use it without doing anything to it.

pureC_StdcallGreeter *g3 = (pureC_StdcallGreeter *)g2;

g3->lpVtbl->setGreeting(g3, "hello, world!");

g3->lpVtbl->greet(g3);

g3->lpVtbl->dtor(g3);

free(g2);

/*

// cdecl passes this via ecx in x86, and not as the first argument;

// this means that this argument cannot be accessed in C without

// inline assembly or equivelent. Trying to run code below will cause a runtime error.

pureC_CdeclGreeter *g4 = (pureC_CdeclGreeter *)g;

g4->lpVtbl->setGreeting(g4, "hello, world!");

g4->lpVtbl->greet(g4);

g4->lpVtbl->dtor(g4);

free(g);

*/

delete g;

}

int main(int argc, char **argv)

{

test();

system("pause");

return 0;

}

TLDR;它不同于cdecl使得C++类在使用此约定的平台上不能从C使用,因为为了向方法发送“This”,您必须将ecx寄存器设置为“This”的地址,而不是仅仅推送它,并且同样如果你想要在C中实现一个C++可以识别的类,那么该方法需要从ecx寄存器中获取这个指针,C无法访问这个指针而没有内联装配或等效。

stdcall具有这个不错的属性,使用stdcall的类可以轻松地同时从C或C++使用,而无需对它们执行任何操作。

所以你只能#define __stdcall只要你不处理__thiscall;尽管可能还有其他一些细微的区别。

linux编译 __stdcall,Linux中是否有STDCALL?相关推荐

  1. spdlog linux编译出错,Linux下编写Makefile引入第三方库

    Linux下编写Makefile引入第三方库 前言:一直在使用CmakaList 生成Makefile文件,其实很少去写Makefile,但是最近帮朋友处理了一个Makefile引入第三方库的问题,就 ...

  2. linux 编译openmp,Linux 系统中OpenMP

    转自:http://hi.baidu.com/linzch/blog/item/db3252fb6227c01e6c22eb21.html *怎么在Linux上运行OpenMP程序? > 只需要 ...

  3. Linux编译dhcpd,linux中搭建dhcpd服务器

    这一次咱们来共同看一看如何在linux中搭建dhcp服务器: 首先呢dhcp服务分为客户端IP地址动态分配服务和dhcp中继服务,小编在这里用linux系统搭建一个为客户端动态分配IP地址的dhcp服 ...

  4. linux编译ace,Linux下编译ACE

    操作系统:Centos4.7 ACE版本:ACE-6.0.2 安装过程: 下载ACE-6.0.2.tar.gz. 下载完成后将其解压tar -zxvf ACE-6.0.2.tar.gz用户登陆目录.我 ...

  5. linux编译bzip2,linux bzip2 命令详解

    linux bzip2 命令详解 功能说明:.bz2文件的压缩程序. 语 法:bzip2 [-cdfhkLstvVz][--repetitive-best][--repetitive-fast][- ...

  6. linux 编译配置文件,Linux程序源码编译安装的configure配置详解

    Linux环境下,如果通过源代码编译安装程序的简单过程可以 描述为:./configure-->make-->make install.其中./configure配置脚本功能就是对你的系统 ...

  7. linux编译ice,linux环境下编译安装ICE

    前面我们讲过了在linux环境下通过rpm的方式来安装ICE,这种安装方式可以是比较简单的,自己在安装过程中发现后面PHP无法装在IcePHP.sp模块,也有可能自己在安装过程中某个地方出错了.又尝试 ...

  8. linux编译sqrt,linux c sqrt

    我想到的一个简单可能性是,在常见情况下,每个值保留一个压缩数组,每个值2位,而每个值分隔一个4字节(原始元素索引为24位,实际值为8位,因此(idx << 8) | value))其他的. ...

  9. ffmpeg arm linux编译,arm linux 移植 ffmpeg 库 + x264 + x265

    背景 Ffmpeg 中带有h264的解码,没有编码,需要添加x264.libx264是一个自由的H.264编码库,是x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx264. ...

  10. linux 编译缓存,Linux磁盘缓存(disk cache)详解

    在Linux系统里通过free命令,我们经常可以看到类似下面的输出: $ free -m total used free shared buffers cached Mem: 24097 21665 ...

最新文章

  1. 中科院德州扑克AI获卓越论文奖!AAAI 2022开奖,吴恩达获纪念讲座奖
  2. ## 使用MapReduce程序完成相关数据预处理
  3. Leetcode题库 110.平衡二叉树(递归 C实现)
  4. python 当前目录_virtualenvwrapper打造多版本Python环境
  5. vuex Payload 荷载
  6. PHP函数之HTMLSPECIALCHARS_DECODE
  7. outside of class is not definition
  8. 高效的css命名约定
  9. 洛谷OJ P3865 【模板】ST表
  10. HeadFirstJava——2_类与对象
  11. C语言大作业 商品库存管理系统
  12. 计算机视觉与图形学-神经渲染专题-神经体渲染:实时渲染KiloNeRF
  13. oracle 绑定变量语法,Delphi使用绑定变量法操作Oracle
  14. Cf#595 (Div. 3)D-贪心
  15. 国内外贵金属白银有何区别?
  16. TDengine 单节点Cluster not ready( 群集未就绪) 异常问题分析及解决方案
  17. java模拟器ios版安装失败,iOS 在模拟器上安装 Debug 调试包(.app)
  18. ubuntu写yacc
  19. 2.OrientDB连接操作
  20. 高级计算机职称论文自述,教师评职称自述

热门文章

  1. teamviewer路由器设置虚拟服务器,远程控制软件TeamViewer的配置详细操作步骤
  2. wmic冻结进程_WMIC的用法
  3. MacBook上有哪些实用必备软件(2020年集合篇)
  4. 碧桂园+电子签章系统,打造印控中台,实现集团印章管控一体化
  5. vega56刷64_A卡—Vega56的简易玩法
  6. 大数据apache-spark问题总结
  7. Android对接蓝牙打印机
  8. 遥感学习笔记(四)——遥感数据分类
  9. php 百望电子发票,百望云电子发票服务平台开票工具
  10. 机器视觉软件能够做什么?-龙熙视觉机器视觉培训李杰