[英]Invalid use of non-static member function - Class Member Function Calling Another Class Member Function
I keep getting this message when I try to compile:当我尝试编译时,我不断收到此消息:
task.c++:54:102: error: invalid use of non-static member function
this->createTask(&otherTask, this->otherMain, mainTask.regs.eflags, (uint32_t*)mainTask.regs.cr3);
Here is my task.c++ function:这是我的 task.c++ 函数:
#include "task.h"
static task_q *runningTask;
static task_q mainTask;
static task_q otherTask;
static PhyiscalMemoryManager *pmm_task;
static Heap *heap_task;
extern void switch_task_a();
TaskManager::TaskManager(Heap *heap)
{
heap_task = heap;
}
TaskManager::~TaskManager()
{}
Task::Task()
{}
Task::~Task()
{}
void TaskManager::otherMain()
{
printf("Hello multitasking world!"); // Not implemented here...
preempt();
}
void TaskManager::createTask(task_q* task, void(*task_main)(), uint32_t flags, uint32_t* pageDir)
{
task->regs.ebx = 0;
task->regs.ecx = 0;
task->regs.edx = 0;
task->regs.esi = 0;
task->regs.edi = 0;
task->regs.eflags = flags;
task->regs.eip = (uint32_t) task_main;
task->regs.cr3 = (uint32_t) pageDir;
task->regs.esp = (uint32_t) (heap_task->k_malloc(TASK_STACK_SIZE)) + 0x1000; // Not implemented here
task->next = 0;
}
void TaskManager::init_tasking()
{
// Get EFLAGS and CR3
__asm __volatile("movl %%cr3, %%eax; movl %%eax, %0;":"=m"(mainTask.regs.cr3)::"%eax");
__asm __volatile("pushfl; movl (%%esp), %%eax; movl %%eax, %0; popfl;":"=m"(mainTask.regs.eflags)::"%eax");
this->createTask(&otherTask, this->otherMain, mainTask.regs.eflags, (uint32_t*)mainTask.regs.cr3);
mainTask.next = &otherTask;
otherTask.next = &mainTask;
runningTask = &mainTask;
}
void TaskManager::switchTask(Registers *old, Registers *new_)
{
switch_task_a();
}
void TaskManager::preempt()
{
task_q *last = runningTask;
runningTask = runningTask->next;
switchTask(&last->regs, &runningTask->regs);
}
And here is my task.h:这是我的 task.h:
#ifndef _TASK_H_
#define _TASK_H_ 1
#include <stdarg.h>
#include <stdint.h>
#include "gdt.h"
#include "stdio.h"
#include "heap.h"
#include "pmm.h"
#define TASK_STACK_SIZE 0x2000
typedef struct {
uint32_t eax, ebx, ecx, edx, esi, edi,
esp, ebp, eip, eflags, cr3;
} Registers;
typedef struct task_q {
Registers regs;
struct task_q *next;
} task_q;
class Task
{
friend class TaskManager;
public:
Task();
~Task();
private:
};
class TaskManager
{
public:
TaskManager(Heap *heap);
~TaskManager();
void init_tasking();
static void createTask(task_q* task, void(*task_main)(), uint32_t flags, uint32_t* pageDir);
void preempt();
private:
void switchTask(Registers *old, Registers *new_);
void otherMain();
};
#endif
Is this something wrong with calling this->OtherMain()
inside this->createTask()
?在this->createTask()
调用this->OtherMain()
有什么问题吗?
void(*task_main)()
is expecting a pointer to a function. void(*task_main)()
需要一个指向函数的指针。 You attempt to feed it void otherMain();
你试图喂它void otherMain();
which is a class method and has a hidden this
parameter.这是一个类方法并且有一个隐藏的this
参数。
This stuff gets a little whacky.这东西变得有点古怪。 Here is a great write-up on some of the badness and how to avoid it.这是一篇关于一些坏处以及如何避免它的好文章。
You're going to have to do a bit of a rethink on how you do this.你将不得不重新思考如何做到这一点。 You can use a static void task_runner(void * userparam)
method (no this
) and a user parameter that can be cast by the static method to provide a TaskManager
on which you can invoke otherMain
.您可以使用static void task_runner(void * userparam)
方法(没有this
)和可以由静态方法转换的用户参数来提供一个TaskManager
,您可以在其上调用otherMain
。 You can turn void(*task_main)()
into void(TaskManager::*task_main)()
and you'll still have to provide a TaskManager
to invoke the method pointer on.您可以将void(*task_main)()
转换为void(TaskManager::*task_main)()
并且您仍然必须提供一个TaskManager
来调用方法指针。
It's a really nasty business, but can I interest you in exploring std::bind
instead?这是一项非常糟糕的业务,但我可以让您对探索std::bind
感兴趣吗?
Task runner is something along the lines of this:任务运行器是这样的:
class taskRunner
{
public:
virtual execute() = 0;
static void task_runner(void * userparam)
{
taskRunner* task = (taskRunner*)userparam;
task->execute();
}
};
Downsides are everything you try to run MUST be a class that inherits taskRunner
and implements execute
and something must keep track of userparam
.缺点是您尝试运行的所有内容都必须是一个继承taskRunner
并实现execute
的类,并且必须跟踪userparam
。 Non trivial effort is involved, but what the hell.涉及非平凡的努力,但到底是什么。 Looks like you're writing yourself an OS.看起来您正在为自己编写操作系统。 Non trivial effort all-around.全方位的非平凡努力。
Probably better for you it to push the abstraction up one level and only accept free functions and static methods.将抽象提升一级并且只接受自由函数和静态方法可能对您更好。 Let the function being run sort out whether it's a class or not.让正在运行的函数弄清楚它是否是一个类。
This means that otherMain
cannot be a member of TaskManager
unless it's static and this will require a re-write of TaskManager
to allow cross-cutting behaviour like a task's ability to sleep, yield its timeslice, and other OS goodies to be called without knowing the internals of TaskManager
.这意味着otherMain
不能是TaskManager
的成员,除非它是静态的,这将需要重新编写TaskManager
以允许横切行为,例如任务的睡眠能力、产生其时间片和其他操作系统好东西在不知道TaskManager
内部结构。
otherMain
could just be otherMain
可能只是
void otherMain()
{
printf("Hello multitasking world!");
yield(); // a free function that calls into the system's TaskManager to preempt
}
The second parameter to createTask()
is a: createTask()
的第二个参数是:
void(*task_main)()
This is a pointer to a function that returns void
.这是一个指向返回void
的函数的指针。
You are passing a:您正在通过:
this->otherMain
otherMain
is not a function that returns void
. otherMain
不是返回void
的函数。 It is a class member that returns void
.它是一个返回void
的类成员。 A class member is not exactly the same as a function.类成员与函数并不完全相同。
The correct parameter type for createTask
, to match a class method that returns void would be:与返回 void 的类方法匹配的createTask
的正确参数类型是:
void (TaskManager::*task_main)()
and the otherMain
class method can be passed as simply:和otherMain
类方法可以简单地传递:
&TaskManager::otherMain
This would solve the immediate problem of the compilation error for this function call.这将解决此函数调用的编译错误的直接问题。
However, you will likely now have a new, different problem.但是,您现在可能会遇到一个新的、不同的问题。 Your existing code attempts to stuff the function pointer into something that resembles a CPU register.您现有的代码尝试将函数指针填充到类似于 CPU 寄存器的内容中。
Well, you don't have a function pointer any more.好吧,您不再有函数指针了。 You now have a class method pointer.您现在有一个类方法指针。 Whether or not the existing code will work, as is, depends on your C++ implementation.现有代码能否正常工作取决于您的 C++ 实现。 Probably not, but that would be a different question.可能不是,但这将是一个不同的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.