带参数的Void *函数
对于我正在尝试编写的应用程序,我需要能够在interface
中写入GLEnable(GL_REPEAT)
(得到这个工作)。一旦用户这样做,系统应该用正确的参数调用该函数。带参数的Void *函数
对于这一点,我使用以下变量来获得正确的功能:
std::map<std::string, void(*)(GLenum)> glEnableDisable;
并通过存储在它的数据:
glEnableDisable["glEnable"] = glEnable;
glEnableDisable["glDisable"] = glDisable;
(注意上面给出警告“'='不能从'void(__stdcall *)(GLenum)'转换为'void(__cdecl *)(GLenum)'”)
最后,调用函数通过:
((void (*)(GLenum)) Main.glEnableDisable[SplittedUp[0]])(Parameter);
现在,我不知道我做错了。我有这个没有参数工作正常,但我真的需要这个参数。
由于提前,
乔伊
更改此:
std::map<std::string, void(*)(GLenum)> glEnableDisable;
这样:
std::map<std::string, std::function<void(GLenum)>> glEnableDisable;
,再也不用担心再次调用约定。一个std::function
能够存储任何函数或可调用对象,无论它的调用约定是什么。不需要
演员:
Main.glEnableDisable[SplittedUp[0]])(Parameter);
谢谢:)这使得void *函数非常容易o.o –
的问题是“如何店std::map<std::string, void(*)(GLenum)>
接受参数的函数指针”?如果是,那么答案是:这是不可能的,因为你声明了一个具有固定函数指针签名的映射。并且代码中的签名是,存储的函数指针不接受任何参数。
如果你想存储的参数,那么你有两个选择:
访问该参数不超过栈和调用指定的函数所提供的参数,包装函数。
为您正在使用的每个函数指针签名创建一个映射。
提示:幸运的是,由于错误的调用约定,程序没有崩溃。建议将呼叫约定修改为__cdecl
。
应该在映射中的函数都使用FunctionName(GLenum)签名(如果我没有误解你的话)。我可以使用什么地图来正确存储签名?该地图只包含2个函数,glDisable和glEnable,尽管为了整洁起见,我宁愿不使用if语句来找出它是哪一个。 –
@JoeyvanGangelen:不幸的是它不可能。容器(例如std :: map)只接受指定的签名。每个参数和它的数据类型都会改变签名。如果你想使它通用,你没有别的选择选择1.另一个解决方案是一个工作线程,它读取ab命令enum和一个通用数据结构来存放每个参数。在switch/case模块中,你可以识别命令并提取参数传递给函数。我知道没有优雅的解决方案,但它会工作。 –
很明显:
void(*)(GLenum)
是不正确的原型为GLenum
功能。
此处假定调用约定为C
,在Visual Studio中默认为__cdecl
。但是,您要调用的实际功能使用不同的调用约定,即__stdcall
。
像这样的东西应该解决的问题:
typedef void (__stdcall *GLenumFunc)(int, int); // or whatever your params are
//...
std::map<std::string, GLenumFunc> glEnableDisable;
至于调用约定是什么:Calling Conventions on x86 platforms
这是从来没有真正的“工作正常”不带参数。你很幸运,你没有因为使用错误的调用约定而崩溃('__stdcall'与'__cedcl') – PaulMcKenzie
__stdcall来自Visual Studio给出的警告。它不是我的代码的一部分(我试图从OpenGL调用glEnable函数) –
忽略警告给自己的危险。你应该问自己(或者*)什么是__stdcall什么是__cdecl,为什么VS会警告我甚至不在我的代码中的东西?甚至在尝试运行任何东西之前。 –