Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Patrick Egli

Treue Seele

  • »Patrick Egli« ist der Autor dieses Themas

Beiträge: 161

Wohnort: Rainstrasse 38

  • Private Nachricht senden

1

04.12.2010, 10:46

Funktion ausserhalb der DLL deklariern

Hi

Ich bin zur Zeit am Programmieren einer DLL. Ich will nun, dass der Benutzer eine Funktion selber deklarieren kann, welche ich bereits in der DLL als Prototyp definiert habe.
Ich habe dieses Vorgehen bereits hingekriegt, dedoch mit einer Memberfunktion einer Klasse. Wie kann ich das nun mit einer Funktion machen, welche nicht in einer Klasse definiert wird?

Hier ist der Code mit der Klasse:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
veResult SetLightColor(veColor LightColor); // Memberfunktion der Klasse veLight

veResult veLight::SetLightColor(veColor LightColor) // Die Deklaration in der Hauptanwendung
{
    // ......

    return VE_OK;
}


Da es etwas umständlich ist für den Benutzer über die Klasse eine Funktion zu deklarieren, will ich lieber eine Funktion ohne Klasse.

Kann mir jemand dabei helfen?

LG Patrick

2

04.12.2010, 12:21

Also erst einmal hast du - so vermute ich - die Begriffe deklarieren und definieren vertauscht. Hier ist ein Link der das vielleicht nochmal erklärt.

Wenn ich das aber richtig verstanden habe, dann möchtest du eine Funktion in deiner DLL deklrarieren (als Prototyp) und die Definition der Funktion in die Anwendung packen, die nachher die DLL einbindet?!
Meinst du wirklich du kannst den Quellcode deiner DLL fehlerlos kompilieren, wenn zu einer deklarierten Funktion die entsprechende Definition nicht zu finden ist?!

Aber vielleicht helfen dir virtuelle Funktionen weiter. Hier auch ein Link dazu.

Ansonsten erklär doch mal genau was du vorhast, dann wird's für uns einfacher dir zu helfen.

Gruß
SaRu_

Patrick Egli

Treue Seele

  • »Patrick Egli« ist der Autor dieses Themas

Beiträge: 161

Wohnort: Rainstrasse 38

  • Private Nachricht senden

3

04.12.2010, 13:34

Oops, definiere und deklarieren vertauscht, hoppla.

Ich will das der Benutzer die Funktion in der Hauptanwendung definieren kann. Dann gibt es eine veRunGame() Funktion, welche die Funktionen Render und Move abwechslungsweiss ausführt. Ich habe vorhin nur mit SetLightColor einen Test gemacht, eigentlich sollten die Funktionen Render und Move durch den Benutzer definiert werden.

Mit diesem Vorgehen muss der Benutzer keine Zeiger als Paramerter übergeben, wie bei der TriBase-Funktion tbDoMessageLoop. Ich rufe dann die Funktionen in der DLL auf, in der Funktion veRunGame. Mit diesem Aufruf sollten dann die vom Benutzer definierten Funktionen abwechslungsweise ausgeführt werden.

Ich hoffe ich habe mein Vorgehen verständlich erklären können.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

04.12.2010, 13:40

Ich fürchte was du vorhast ist leider nicht möglich. Allein das Exportieren von Klassen in dlls ist generell schon ein rein Microsoft spezifisches Feature und afaik kannst du nur eine ganze Klasse exportieren und nicht einzelne Member importieren und den Rest exportieren...

5

04.12.2010, 14:48

Sowas sollte, meinem Wissen nach, nicht moeglich sein.
Du koenntest das ganze fuer Klassen machen und dann einen Aufbau ueber virtuell machen, wie SaRu schon geschrieben hat.

Patrick Egli

Treue Seele

  • »Patrick Egli« ist der Autor dieses Themas

Beiträge: 161

Wohnort: Rainstrasse 38

  • Private Nachricht senden

6

04.12.2010, 19:13

So ich habe nun probiert mit einer Klasse und mit einer virtuellen Memberfunktion zu arbeiten. Wenn ich nun allerdings die viruelle Memberfunktion in der veRunGame() Methode aufrufe, gibt es unaufgelöste externe Symbole. Deshalb habe ich die Funktion bereits definieren müssen. Ich habe lediglich return VE_DEFAULT zurückgeben. Dann wurden keine unaufgelöste externe Symbole angezeigt.

Doch danach habe ich die beiden Funktionen RenderScene und MoveScene in der Hauptanwendung definiert, es gab auch keine Fehler beim Kompilieren, doch beim Ausführen des Programmes wurde nichts angezeigt. Wahrscheinlich hat der Compiler die bereits definierte Funktion in meiner DLL gewählt, bei welcher nur VE_DEAUFLT zurückgegeben wird.

Hier ist ein Codeausschnitt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
virtual veResult RenderScene(float fTime);                                                                                  // Die beiden virtuellen Memberfunktionen der Klasse veScene
    virtual veResult MoveScene(float fTime);

veResult veScene::RenderScene(float fTime)
{
    // -----------------------------------------------------------------------------------
    // Diese Funktion wird genommen, wenn der Benutzer die RenderScene Funktion noch nicht definiert hat.
    // -----------------------------------------------------------------------------------
    
    return VE_DEFAULT;
}

veResult veScene::MoveScene(float fTime)
{
    // -----------------------------------------------------------------------------------
    // Diese Funktion wird genommen, wenn der Benutzer die MoveScene Funktion noch nicht definiert hat.
    // -----------------------------------------------------------------------------------
    
    return VE_DEFAULT;
}

VE_API veResult veRunGame()
{
    // Variablen deklarieren
    MSG         msg;
    LONGLONG    StartTime;
    LONGLONG    EndTime;
    double      Time;
    BOOL        bQuit = FALSE;
    BOOL        bInput = FALSE;

    ZeroMemory(&msg, sizeof(MSG));

    Time = 0.0;

    // Nachrichtenschleife der VisualEngine
    while(!bQuit)
    {
        // Die Startzeit berechnen
        QueryPerformanceCounter((LARGE_INTEGER*)(&StartTime));

        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);

            if(msg.message == WM_QUIT)
            {
                bQuit = TRUE;
            }
        }

        // Den aktuellen Status der Aktivität von dem Input bekommen
        bInput = veScene::SceneInstance().GetInputActivity();

        // Wenn Input vom Benutzer gebrauch wird, dann wird das Input geupdatet.
        if(bInput == true)
        {
            veScene::SceneInstance().UpdateInput();
        }

        ve_g_dNumSecsPassed = Time;

        if(veScene::SceneInstance().RenderScene(Time) == VE_OK)
        {
            // Alles ist in Ordnung
        }

        if(veScene::SceneInstance().MoveScene(Time) == VE_OK)
        {
            // Endzeit berechnen
            QueryPerformanceCounter((LARGE_INTEGER*)(&EndTime));
            if(EndTime == StartTime) Time = 0.0001;
            Time = (float)(EndTime - StartTime) / ve_g_dFrequency;
        }

        // Endzeitpunkt messen
        QueryPerformanceCounter((LARGE_INTEGER*)(&EndTime));
        if(EndTime == StartTime) Time = 0.0001;
        Time = (float)(EndTime - StartTime) / ve_g_dFrequency;

        // Den Zeitzähler erhöhen
        ve_g_dTime += Time;
    }

    return VE_OK;
}

// Das Hauptprogramm
veResult veScene::RenderScene(float fNumSecsPassed)
{
    Scene->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    Scene->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    Scene->BeginScene();

    pSpaceship->RenderMesh();

    Scene->EndScene();
    Scene->Present(NULL, NULL, NULL, NULL);

    return VE_OK;
}

veResult veScene::MoveScene(float fNumSecsPassed)
{
    D3DXMATRIX mRotation;

    static float Translation = 8.0f;
    static float Light = 0.0f;

    static float index = 0.0f;
    index += 0.03f;

    D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 20.0f, Translation),
                                 &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
                                 &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

    Scene->SetTransform(D3DTS_VIEW, &matView);

    D3DXMatrixRotationY(&mRotation, index);
    Scene->SetTransform(D3DTS_WORLD, &mRotation);

    if(Scene.KeyDown(VE_KEY_UP))
    {
        Translation += 0.3f;
    }
    if(Scene.KeyDown(VE_KEY_DOWN))
    {
        Translation -= 0.3f;
    }
    if(Scene.KeyDown(VE_KEY_W))
    {
        Light += 0.3f;
    }
    if(Scene.KeyDown(VE_KEY_S))
    {
        Light -= 0.3f;
    }

    pLight->SetLightPosition(veVector3(0.0f, 0.0f, Light));

    g_fTime += fNumSecsPassed;

    return VE_OK;
}

veRunGame(); // Der Aufruf von veRunGame()


Was habe ich falsch gemacht, kann mir jemand dabei helfen?

7

04.12.2010, 19:45

Ich denke mal, dass es in etwa so gelöst wird ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
class Engine
{
protected:
   virtual void Render() = 0; // Abstrakte Funktion, die in der abgeleitende Klasse definiert werden muss
   virtual void Move(float fTime) = 0;
public:
   virtual ~Engine(){}
    
   void RenderLoop(); // Deine MessageLoop
};


Dann leitest du einfach in der Anwendung eine Klasse ab ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
class Game : public Engine
{
private:
    void Render(); // Kannst du die Funktion selber schreiben, genau wie Move
    void Move(float fTime);
public:
    ~Game();
};


Dadurch kannst du dann deine Render- und Movefunktion in deiner Anwendung schreiben, und die Render Loop weiß auch, welche Funktionen er aufrufen muss ;)
Hoffe mal, dass es so richtig ist.
Mfg Male

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Male« (04.12.2010, 20:00)


Werbeanzeige