2016-04-14 9 views
4

Ich entwickle ein C++ - Tool, das transparent für das Hauptprogramm ausgeführt werden sollte. Das heißt: Wenn der Benutzer das Werkzeug einfach mit seinem Programm verknüpft, wird das Werkzeug aktiviert. Dazu muss ich zwei Funktionen aufrufen, Funktion a(), bevor main() Steuerung und Funktion b() nach main() endet.So rufen Sie eine C++ - Funktion auf, nachdem main() beendet wurde

Ich kann leicht das erste tun, indem ich eine globale Variable in meinem Programm deklariere und es durch Rückkehrcode von a() initialisieren lasse. d.h

int v = a() ; 

aber ich kann nicht einen Weg rufen b() nach main() Oberflächen finden?

Kann jemand einen Weg finden, dies zu tun?

Das Tool läuft unter Windows, aber ich möchte keine OS-spezifischen Anrufe verwenden.

Danke, George

+2

Sie können ein Objekt in main in Call-Funktion 'b' in seinem Destruktor erstellen – user463035818

+0

Ist nicht [' atexit() '] (http://linux.die.net/man/3/atexit) für Sie? – MikeCAT

+4

Machen Sie Ihren globalen Variablen-Klassen-Typ und setzen Sie den Code in seinen Destruktor –

Antwort

4

LÖSUNG IN C:

einen Blick auf atexit haben:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
void bye(void) 
{ 
    printf("That was all, folks\n"); 
} 
int main(void) 
{ 
    long a; 
    int i; 
    a = sysconf(_SC_ATEXIT_MAX); 
    printf("ATEXIT_MAX = %ld\n", a); 
    i = atexit(bye); 
    if (i != 0) { 
     fprintf(stderr, "cannot set exit function\n"); 
     exit(EXIT_FAILURE); 
    } 
    exit(EXIT_SUCCESS); 
} 

http://linux.die.net/man/3/atexit

bedeutet dies jedoch immer noch, dass Sie Zugriff auf Ihre main und Sie können den atexit Anruf hinzufügen. Wenn Sie keinen Zugriff auf die Hauptleitung haben und Sie diesen Funktionsaufruf nicht hinzufügen können, glaube ich nicht, dass es eine Option gibt.

EDIT:

SOLUTION in C++:

sudgested als ein C++ Äquivalent von std ist. Ich fügen Sie einfach hier in einem Beispiel, das ich über den Link direkt unter dem Code verfügbar kopiert:

#include <iostream> 
#include <cstdlib> 

void atexit_handler_1() 
{ 
    std::cout << "at exit #1\n"; 
} 

void atexit_handler_2() 
{ 
    std::cout << "at exit #2\n"; 
} 

int main() 
{ 
    const int result_1 = std::atexit(atexit_handler_1); 
    const int result_2 = std::atexit(atexit_handler_2); 

    if ((result_1 != 0) or (result_2 != 0)) { 
     std::cerr << "Registration failed\n"; 
     return EXIT_FAILURE; 
    } 

    std::cout << "returning from main\n"; 
    return EXIT_SUCCESS; 
} 

http://en.cppreference.com/w/cpp/utility/program/atexit

+0

Da OP erwähnt, dass das Tool unter Windows läuft, könnte ein Link zur Windows-Version von 'atexit' angebracht sein: https://msdn.microsoft.com/en-us/library/tze57ck3.aspx – computerfreaker

+1

Die Frage ist mit C++ markiert Diese Antwort ist in C. Nicht, dass es einen großen Unterschied geben würde. – Biffen

+1

@computerfreaker Oder ['std :: atexit]] (http://en.cppreference.com/w/cpp/utility/program/atexit). – Biffen

1

Wenn Sie zufrieden sind mit einem einzigen Compiler und Nicht-Standard-C/C++ zu halten, dann GCC __attribute__((constructor)) und __attribute__((destructor)) könnte von nutzen sein:

#include <stdio.h> 

void __attribute__((constructor)) ctor() 
{ 
    printf("Before main()\n"); 
} 

void __attribute__((destructor)) dtor() 
{ 
    printf("After main()\n"); 
} 

int main() 
{ 
    printf("main()\n"); 

    return 0; 
} 

Ergebnis:

Before main() 
main() 
After main() 
+1

Die Frage wird als C++ markiert, warum würden Sie auf nicht-Standard-und nicht-portable Lösungen zurückgreifen? – Chiel

9

Verwenden Sie RAII, wobei a und b im Konstruktor/Destruktor aufgerufen werden.

class MyObj { 
MyObj() 
    { 
    a(); 
    }; 
~MyObj() 
    { 
    b(); 
    }; 
}; 

Dann haben nur eine Instanz von MyObj außerhalb des Anwendungsbereichs der Haupt()

MyObj obj; 

main() 
{ 
    ... 
} 

Einige Dinge zu beachten.

  • Dies ist Moor-Standard C++ und funktioniert auf jeder Plattform
  • Sie diesen Code ohne Änderung jeden bestehende Quelle verwenden können, indem Sie einfach Ihre Instanz von MyObj in einer separaten Übersetzungseinheit mit.
  • Während es vor und nach main() ausgeführt wird, werden alle anderen Objekte, die außerhalb von main erstellt wurden, ebenfalls zu diesem Zeitpunkt ausgeführt. Und Sie haben wenig Kontrolle über die Bestellung der Konstruktion/Zerstörung Ihres Objekts, unter anderem.
+1

Sie könnten die Instanz als statisches Mitglied von 'MyObj' haben und alles in der Klasse privat machen, wenn es wichtig ist, dass jede Funktion nur einmal aufgerufen wird. – Biffen

+0

@Biffen Ja. Das könnte Sinn machen. Ich lege das Objekt nur explizit vor 'main()', um das Beispiel einfach und offensichtlich zu halten. – Roddy

+0

Danke !! Das ist die einfachste Lösung für mein Problem. Warum ich nicht selbst an den Destruktor gedacht habe ..... –

1

Ist keine globale Variable vor main aufgebaut und danach zerstört? Ich habe einen Test struct gemacht, dessen Konstruktor vor main und dem Destruktor danach aufgerufen wird.

#include <iostream> 

struct Test 
{ 
    Test() { std::cout << "Before main..." << std::endl; } 
    ~Test() { std::cout << "After main..." << std::endl; } 
}; 

Test test; 

int main() 
{ 
    std::cout << "Returning now..." << std::endl; 
    return 0; 
} 
0

Alternativ zum destructor, können Sie atexit() in ähnlicher Weise verwenden - in C++, brauchen Sie keinen Zugang zu main() haben atexit dort zu registrieren. Sie können tun, dass auch sie in Ihrem a() - zum Beispiel:

void b(void) { 
    std::cout << "Exiting.\n"; 
} 

int a(void) { 
    std::cout << "Starting.\n"; 
    atexit(b); 
    return 0; 
} 

// global in your module 
int i = a(); 

aber sagt, dass ich auch das globale C++ Klassenobjekt bevorzugen würde, die die b() Sachen in seinem destructor nennen.

Verwandte Themen