首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux中有STDCALL吗?

Linux中有STDCALL吗?
EN

Stack Overflow用户
提问于 2010-06-16 22:34:23
回答 3查看 28.1K关注 0票数 22

我正在尝试将Windows应用程序移植到Linux上。此应用程序使用__stdcall属性标记一些函数。然而,一位朋友告诉我,stdcall只在Windows上使用,在Linux上没有意义(但确实存在于Windows中,GCC)。

搜索谷歌-一些结果表明在Linux中有stdcall

Linux中有stdcall吗?

此外,GCC指出:__attribute__((__stdcall__))__attribute__((stdcall)) (在stdcall附近没有下划线)。

哪一个是首选的(如果应用于Linux )?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-06-16 22:36:42

最简单的解决方案是在Linux上有条件地将__stdcall定义为nothing。

票数 15
EN

Stack Overflow用户

发布于 2010-06-16 23:31:23

这里有一个指向MSDN上的__stdcall描述的链接:http://msdn.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx

它只用于调用WinAPI函数。要将这样的Windows应用程序移植到Linux上,您需要的远不止是将__stdcall定义为空:

代码语言:javascript
复制
#ifndef WIN32 // or something like that...
#define __stdcall
#endif

您还需要调用特定于Win32的API函数,而不是Linux API函数。根据Win32应用程序接口的特定部分和应用程序的大小(代码量),它可能介于中等困难和令人望而生畏之间。

app标记为__stdcall的具体功能有哪些?

实际上,GCC的Windows port必须要有__stdcall,因为它应该能够为Win32平台生成一致性代码。但由于在Linux下只有一种标准的调用约定,而且它与默认的编译器输出一致,所以不需要此语句。

您的应用程序不能在Linux下编译的原因几乎肯定是因为它引用了没有在Linux下定义的Linux函数--您需要找到合适的Win32对应物。Linux和Win32 GLibc API-s有很大的不同,不能轻易被替代。

将你的应用移植到Linux上最简单的方法可能是使用Wine,即修改Windows代码,使其在Linux的Wine下顺利运行。即使是最复杂的应用程序,如现代电脑游戏,也是这样在Linux下运行的。

当然,如果您真的希望它在Linux下本机运行,那么移植是唯一的选择。

票数 10
EN

Stack Overflow用户

发布于 2018-02-23 12:03:49

stdcall不仅仅是一种调用约定;除了是一种调用约定之外,它还允许C和C++对象之间的同构。下面是一个例子:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS // disable marking use of strcpy as error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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;
}

这与cdecl在使用此约定的平台上使C++类在C中不可用是不同的,因为为了将" this“发送到一个方法,您必须将ecx register设置为" This”的地址,而不是仅仅推送它,同样,如果您想用C实现一个C++可以识别的类,该方法将需要从ecx寄存器中获取此指针,如果不使用内联汇编或等效方法,该寄存器对于C是不可访问的。

stdcall有一个很好的属性,使用stdcall的类可以很容易地从C或C++中同时使用,而不需要对它们做任何操作。

因此,只要不处理__thiscall,就只能使用#define __stdcall;尽管可能还有其他一些细微的区别。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3054257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档