2016-09-10 1 views
-4

Ich halte diese Nachricht bekommen, wenn ich zu kompilieren versuchen:Ungültige Verwendung von nicht-statische Member-Funktion - Klasse Memberfunktion aufrufen Eine andere Klasse Memberfunktion

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

Hier meine task.c ist ++ Funktion:

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

Und hier ist mein 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 

ist das etwas nicht stimmt mit this->OtherMain() Aufruf in Seite this->createTask()?

+0

Mögliches Duplikat von [ungültige Verwendung der nicht statischen Elementfunktion] (http://stackoverflow.com/questions/29286863/invalid-use-of-non-static-member-function) – gsamaras

+0

@gsamaras das ist die erste Frage Ich sah vor vielen, bevor ich diese Frage – amanuel2

Antwort

0

void(*task_main)() erwartet einen Zeiger auf eine Funktion. Sie versuchen, es void otherMain(); Feed, die eine Klassenmethode ist und hat einen versteckten this Parameter.

Dieses Zeug wird ein bisschen wackelig. Here is a great write-up on some of the badness and how to avoid it.

Sie müssen ein wenig darüber nachdenken, wie Sie das tun. Sie können eine static void task_runner(void * userparam)-Methode (keine this) und einen Benutzerparameter verwenden, der von der statischen Methode umgewandelt werden kann, um eine TaskManager bereitzustellen, auf die Sie otherMain aufrufen können. Sie können void(*task_main)() in void(TaskManager::*task_main)() umwandeln, und Sie müssen immer noch eine TaskManager bereitstellen, um den Methodenzeiger auf aufzurufen.

Es ist ein wirklich schmutziges Geschäft, but can I interest you in exploring std::bind instead?

bearbeiten

Task-Läufer ist etwas entlang der Linien von dieser:

class taskRunner 
{ 
public: 
    virtual execute() = 0; 
    static void task_runner(void * userparam) 
    { 
     taskRunner* task = (taskRunner*)userparam; 
     task->execute(); 
    } 
}; 

Nachteile sind alles, was Sie versuchen, eine Klasse zu laufen muss sein, dass erbt taskRunner und implementiert execute und etwas muss userparam im Auge behalten. Nicht triviale Bemühungen sind beteiligt, aber was zur Hölle. Sieht aus, als würdest du dir selbst ein Betriebssystem schreiben. Nicht triviale Bemühungen rundum.

Wahrscheinlich ist es besser für Sie, die Abstraktion eine Ebene höher zu treiben und nur freie Funktionen und statische Methoden zu akzeptieren. Lass die Funktion, die ausgeführt wird, aussortieren, ob es eine Klasse ist oder nicht.

Das bedeutet, dass otherMain kein Mitglied von TaskManager sein kann, wenn sie statisch ist, und dies wird ein Umschreiben von TaskManager erfordert Verhalten Querschnitt ist wie eine Aufgabe Fähigkeit zu ermöglichen, seine Zeitscheibe zu schlafen, Ausbeute und andere OS Leckereien zu sein genannt, ohne die Interna von TaskManager zu kennen.

otherMain konnte nur

void otherMain() 
{ 
    printf("Hello multitasking world!"); 
    yield(); // a free function that calls into the system's TaskManager to preempt 
} 
+0

stelle, kann ich nicht std :: bind in osdev verwenden. Was ist task_runner() genau in deinem Kontext? – amanuel2

0

Der zweite Parameter ist ein zu createTask() sein:

void(*task_main)() 

Dies ist ein Zeiger auf eine Funktion ist, die void zurückgibt.

Sie passieren ein:

this->otherMain 

otherMain keine Funktion, die void zurückgibt. Es ist ein Klassenmember, der void zurückgibt. Ein Klassenmitglied ist nicht genau das Gleiche wie eine Funktion.

Der korrekte Parametertyp für createTask, eine Klassenmethode übereinstimmen, die wäre void zurückgibt:

void (TaskManager::*task_main)() 

und die otherMain Klassenmethode kann so einfach übergeben werden:

lösen würde

&TaskManager::otherMain 
Diese das unmittelbare Problem des Kompilierungsfehlers für diesen Funktionsaufruf.

Allerdings haben Sie jetzt wahrscheinlich ein neues, anderes Problem. Ihr vorhandener Code versucht, den Funktionszeiger in etwas einzufügen, das einem CPU-Register ähnelt.

Nun, Sie haben keinen Funktionszeiger mehr. Sie haben jetzt einen Klassenmethodenzeiger. Ob der vorhandene Code funktioniert oder nicht, hängt von Ihrer C++ - Implementierung ab. Wahrscheinlich nicht, aber das wäre eine andere Frage.

+0

Nun, die einzigen Aufgaben, die ich erstelle, müssen dann von einem TaskManager stammen? – amanuel2

+0

Egal. Ein Funktionszeiger ist kein Klassenmethodenzeiger. Punkt. –

+0

Nun, wenn ich diesen Fehler hier mache: https://github.com/amanuel2/OS_Mirror/blob/master/task.c%2B%2B#L42 Fehler Bieng: sk.C++: 42:34: Fehler: ungültige Besetzung von Geben Sie 'void (TaskManager :: *)()' ein, um 'uint32_t {aka long unsigned int}' einzugeben Aufgabe-> regs.eip = (uint32_t) task_main; – amanuel2

Verwandte Themen