我正在尝试将Windows应用程序移植到Linux上。此应用程序使用__stdcall属性标记一些函数。然而,一位朋友告诉我,stdcall只在Windows上使用,在Linux上没有意义(但确实存在于Windows中,GCC)。
搜索谷歌-一些结果表明在Linux中有stdcall。
Linux中有stdcall吗?
此外,GCC指出:__attribute__((__stdcall__))和__attribute__((stdcall)) (在stdcall附近没有下划线)。
哪一个是首选的(如果应用于Linux )?
发布于 2010-06-16 22:36:42
最简单的解决方案是在Linux上有条件地将__stdcall定义为nothing。
发布于 2010-06-16 23:31:23
这里有一个指向MSDN上的__stdcall描述的链接:http://msdn.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx
它只用于调用WinAPI函数。要将这样的Windows应用程序移植到Linux上,您需要的远不止是将__stdcall定义为空:
#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下本机运行,那么移植是唯一的选择。
发布于 2018-02-23 12:03:49
stdcall不仅仅是一种调用约定;除了是一种调用约定之外,它还允许C和C++对象之间的同构。下面是一个例子:
#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;尽管可能还有其他一些细微的区别。
https://stackoverflow.com/questions/3054257
复制相似问题