繁体   English   中英

在(Visual)C ++中调用动态创建函数的约定

[英]Calling convention for dynamically created function in (Visual) C++

我使用以下类型在运行时创建一个新函数:

typedef int (*pfunc)(int);

union funcptr {
  pfunc x;
  byte* y;
};

这使我能够在y编写指令,然后调用这样的函数:

byte* p = (byte*)VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

// Write some instructions to p

funcptr func;
func.y = p;

int ret = func.x(arg1); // Call the generated function

了解C ++如何准备参数(调用约定)并因此查找项目属性(Visual C ++)并且我可以看到它使用__cdecl是至关重要的。 它应该根据以下内容在堆栈上放置参数: http//msdn.microsoft.com/en-us/library/aa271989v = vs.60) .aspxhttp://en.wikipedia.org/wiki/X86_calling_conventions #cdecl但是当我查看生成的程序集时,参数将被移动到EAX寄存器。

我想绝对肯定这些论据是如何准备的。 所以我忽略了一些关于cdecl东西,或者是Visual C ++优化调用,如果是这样,我如何确保它不会发生?

最诚挚的问候,Lasse Espeholt

EAX寄存器用于函数的返回值 您在评论中说明您正在使用/Gd进行编译,因此该函数将使用__cdecl 在我看来,使用显式__cdecl标记函数类型pfunc的声明是pfunc ,这样就不会有混淆和不匹配的空间。

当然,没有什么可以阻止你使用编译器支持的其他调用约定之一。 最重要的一点是,无论您采用何种调用约定,都应该明确指定函数指针的调用约定,因为编译器只负责接口的一半。

至少在Linux上,你可能想要使用libffi (外部函数接口),它甚至已被移植到其他系统(包括Windows)。

如果你想在运行时生成机器代码,可以考虑使用GNU闪电 ,DotGnu的libjitLLVM LuaJit的dynasm等你也可以在foo.c生成C代码,通过分配gcc -fPIC -shared foo.c -o foo.so命令和dlopen("./foo.so", RTLD_GLOBAL)来编译它(和Windows具有相同的能力)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM