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

1

13.12.2009, 12:43

Abhänige Headerdateien

Hallo,

da dies mein erster Betrag in euerem wirklich erstklassigen Forum ist möchte ich mich ganz kurz vorstellen und danach dann zum eigentlichen Problem kommen. ;)

Also ich bin 18 Jahre alt und Programmiere nun seit ca. 5 Jahren in C++, sowie PHP,JavaScript, HTML(was man ja eig. nicht Programmieren nennen darf^^), ein wenig C# usw.

So wie erkläre ich jetzt am besten mein Problem?!
Also ich würde sagen ich kann schon einigermaßen gut Programmieren, hab auch Davids großartiges Buch durchgearbeitet und soweit auch alles verstanden. Nun wollt ich mich - zur Übung - an das Programmieren einer eigenen Mathematik-Bibliothek machen. Funktioniert auch alles wurderbar, nur dass ich das Problem hab, dass meine Klasse Vector und meine Klasse Matrix sich gegenseitig benötigen, weil Sie jeweils für die Matrix-Vektor Multiplikation bzw. andersrum für die Translation Methoden der jeweils anderen Klasse aufrufen müssen. Nun meckert der kompliler natürlich, dass je nachdem welche Header ich zuerst einbinde, dass dieser Datei die andere Klasse fehlt.
Ich habs mit Forward-Declaration versucht, aber iwie funktioniert das nicht. Ich glaube ich hab irgendwo iwas überlesen wie es richtig funktioniert aber ich finde einfach keine Antwort auf das was ich möchte.

Ach ja, noch ein Problem, wenn ich bei Microsoft Visual Studio 2008 die internen SSE-Mathematikfunktionen benutzen will um 4-Float Operation gleichzeitig zu machen, muss ich dann in jeder Header-Datei die <xmmintrin.h> neu einbinden?

Ich hoffe mal ihr versteht mein Problem und könnt mir helfen, ich wäre euch sehr dankbar!

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
__declspec(align(16)) class Vector3 
    {
    public:
        union{
            struct{
                F32 x,y,z;
            };
            F32 f[3];
        };

        Vector3(){}
        Vector3(Vector3& v):x(v.x),y(v.y),z(v.z){}
        Vector3(F32 fx,F32 fy,F32 fz):x(fx),y(fy),z(fz){}
        Vector3(F32 af[3]):x(af[0]),y(af[1]),z(af[2]){}
        Vector3(F32 xyz):x(xyz),y(xyz),z(xyz){}
        Vector3(__m128& v);

                //usw. nen Paar Operatoren und so


               //Hier das Problem:

              //Vektor mit Matrix

        Vector3 operator * (Matrix& m)
               {
           __m128 result;
           result = _mm_mul_ps (_mm_replicate_x((__m128)(*this)),m(1));
           result = _mm_madd_ps(_mm_replicate_y((__m128)(*this)),m(2),result);
           result = _mm_madd_ps(_mm_replicate_z((__m128)(*this)),m(3),result);
           result = _mm_madd_ps(_mm_replicate_z((__m128)(*this)),m(4),result);
           return Vector3(result);
    }

        //Vektor mit Matrix

        Vector3 operator *= (Matrix& m);
               //In ähnlicher Form definiert

}

//Die Matrix-Klasse ist jetzt im Grunde genau so aufgebaut, nur dass sie 

//für Methoden zur Translation einen Vector& Parameter benutzt


Gruß Hexenkoenig

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

13.12.2009, 12:50

Naja sollte sich mit include guards und forward declarations lösen lassen, zeig mal wie genau es bei dir scheitert...

Mit <xmmintrin.h> is das wie mit jedem andren Header auch, dort wo du das Zeug verwendest muss es halt zuvor deklariert sein, also der Header inkludiert. Wenn das in nem Header is dann musste ihn halt dort inkludieren oder in jeder cpp Datei die deinen Header inkludiert immer zuerst <xmmintrin.h> inkludieren und dann deinen Header...

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

3

13.12.2009, 13:07

Vor dem Problem stand ich letztens auch ;)

Wenn du dich an folgende regeln hälst klappt eigentlich alles:

1) Am Anfang einer Header-datei immer ein include-guard
2) Am Anfang einer header-datei nur eine h-datei includen, wenn eine Forward-deklaration nicht funktioniert würde.
3) Das alles sollte so designed sein, dass die include-reihenfolge in den cpp´s egal ist.

zu 1: sollte klar sein ( wird gemacht um doppelte Definitionen zu verhindern)
zu 2: Der Compiler braucht, wenn du eine klasse richtig benutzt ( hehe damit meine ich keinen Zeiger, referenzen sondern aufm stack bzw als superklasse), die größe ( also wieviel speicherplatz) der instanze der klasse. Bei einer forward-declaration weiß er aber nur dass es die klasse gibt, aber nicht wie groß sie ist. wen du allerdings nur einen Pointer benutzt, brauch er die größe noch nicht zu wissen, da pointer (meistens) gleichgroß sind.

Wenn du das befolgst, sollte es gehen. Ich mache es bei mir immer noch so, dass ich die header-datein, die durch forward-declarationen ersetzt wurden, am ende der headerdatei include. Ich hab das bei noch niemandem gesehen, kann also sein, dass da probleme auftreten, aber bis jetzt hats immer funktioniert ;).


http://www.eventhelix.com/realtimemantra…udePatterns.htm

4

13.12.2009, 13:07

Okay danke

Wow danke für die schnelle Antwort,

da ich versucht habe den Fehler selbst zu reparieren, hab ich mir jetzt alles kaputt gemacht^^. Ich versuch den Fehler zu rekonstruieren, damit ich euch die Fehlermeldung schreiben kann.

Ich editiers dann hier rein.
Danke schon mal
Hexenkoenig

Edit:

Also das ist jetzt die "Test-Vektor-Klasse", die den Fehler reproduziert:

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
#ifndef __VECTOR_H
#define __VECTOR_H

#include <xmmintrin.h>
#include "Include.h"

namespace testit
{
    class Matrix;

#   define _mm_shuffle_param(x,y,z,w)   \
    (x) | ((y)<<2) | ((z)<<4) | ((w)<<6)
#   define _mm_replicate_x(v)   \
    _mm_shuffle_ps((v),(v),_mm_shuffle_param(0,0,0,0))
#   define _mm_replicate_y(v)   \
    _mm_shuffle_ps((v),(v),_mm_shuffle_param(1,1,1,1))
#   define _mm_replicate_z(v)   \
    _mm_shuffle_ps((v),(v),_mm_shuffle_param(2,2,2,2))
#   define _mm_replicate_w(v)   \
    _mm_shuffle_ps((v),(v),_mm_shuffle_param(3,3,3,3))
#   define  _mm_madd_ps(a,b,c)  \
    _mm_add_ps(_mm_mul_ps((a),(b)),(c))
#   define  _mm_madd_ss(a,b,c)  \
    _mm_add_ss(_mm_mul_ss((a),(b)),(c))


    __declspec(align(16)) class Vector3 
    {
    public:
        union{
            struct{
                float x,y,z;
            };
            float f[3];
        };

        Vector3(){}
        Vector3(Vector3& v):x(v.x),y(v.y),z(v.z){}
        Vector3(float fx,float fy,float fz):x(fx),y(fy),z(fz){}
        Vector3(float af[3]):x(af[0]),y(af[1]),z(af[2]){}
        Vector3(float xyz):x(xyz),y(xyz),z(xyz){}
        Vector3(__m128& v);

        //Operatoren

        operator __m128();

        inline Vector3& operator = (Vector3& v){
            x=v.x;
            y=v.y;
            z=v.z;
            return *this;
        }

        //Vektor mit Matrix

        Vector3 operator * (Matrix& m){
            __m128 result;
            result = _mm_mul_ps (_mm_replicate_x((__m128)(*this)),m(1));
            result = _mm_madd_ps(_mm_replicate_y((__m128)(*this)),m(2),result);
            result = _mm_madd_ps(_mm_replicate_z((__m128)(*this)),m(3),result);
            result = _mm_madd_ps(_mm_replicate_z((__m128)(*this)),m(4),result);
            return Vector3(result);
        };

        //Vektor mit Matrix

        Vector3 operator *= (Matrix& m);
    };
}
#endif


Die dazugehörtige Matrix-Klasse:

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
#ifndef __MATRIX_H
#define __MATRIX_H

#include <xmmintrin.h>
#include "Include.h"

namespace testit
{
    __declspec(align(16)) class Matrix
    {
    public:
        union{
            struct{
                float m11,m12,m13,m14;
                float m21,m22,m23,m24;
                float m31,m32,m33,m34;
                float m41,m42,m43,m44;
            };
            float m[4][4];
        };

        Matrix(){}
        Matrix(float nAll): m11(nAll),m12(nAll),m13(nAll),m14(nAll),
            m21(nAll),m22(nAll),m23(nAll),m24(nAll),
            m31(nAll),m32(nAll),m33(nAll),m34(nAll),
            m41(nAll),m42(nAll),m43(nAll),m44(nAll){}

        Matrix( float n11,float n12,float n13,float n14,
            float n21,float n22,float n23,float n24,
            float n31,float n32,float n33,float n34,
            float n41,float n42,float n43,float n44):   m11(n11),m12(n12),m13(n13),m14(n14),
            m21(n21),m22(n22),m23(n23),m24(n24),
            m31(n31),m32(n32),m33(n33),m34(n34),
            m41(n41),m42(n42),m43(n43),m44(n44){}
        Matrix(Matrix& m):  m11(m.m11),m12(m.m12),m13(m.m13),m14(m.m14),
            m21(m.m21),m22(m.m22),m23(m.m23),m24(m.m24),
            m31(m.m31),m32(m.m32),m33(m.m33),m34(m.m34),
            m41(m.m41),m42(m.m42),m43(m.m43),m44(m.m44){}

        Matrix(__m128& n1, __m128& n2, __m128& n3, __m128& n4);

        Matrix& operator = (Matrix& m);
        bool operator == (Matrix& m);
        inline __m128   operator ()(int i)
        {
            assert(i<5 && i>0);
            return _mm_load_ps(m[i-1]);
        };
        inline float&       operator ()(int i,int j)
        {
            assert(i>0 && i<5);
            assert(j>0 && j<5);
            return m[i-1][j-1];
        };


        //Statische Methoden


        inline static Matrix Identity(){
            return Matrix(  1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f);
        }

        inline static Matrix Translate(Vector3& v){
            Matrix mReturn;
            mReturn =(Identity());
            mReturn.m41 = v.x;
            mReturn.m42 = v.y;
            mReturn.m43 = v.z;
            return mReturn;
        }
    };
}

#endif

und die Include

C-/C++-Quelltext

1
2
3
4
5
6
7
#ifndef __INCLUDE_H
#define __INCLUDE_H

#include "Vector.h"
#include "Matrix.h"

#endif


und letzendlich der Fehler:

Quellcode

1
 error C2064: Ausdruck ergibt keine Funktion, die 1 Argumente übernimmt


Der Fehler verweißt auf die Zeile:

C-/C++-Quelltext

1
result = _mm_mul_ps (_mm_replicate_x((__m128)(*this)),m(1));

Er kennt anscheint den Operator () nicht, den hab ich aber definiert.[/cpp]

Gruß
Hexenkoenig

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

5

13.12.2009, 13:09

Vielleicht hilft dir auch mein Blog Eintrag:
http://www.drakon.ch/?id=&offset=&mobile=0&show_entry=77

6

13.12.2009, 13:27

Sehr Hilfreich!

Der Artikel war wirklich hilfreich, leider weiß ich nicht wie ich diese zyklischen Abhängikeiten bei mir effektiv umgehen kann, weil ich ja in der Vektor.h den Operator () brauche um eine Zeile der Matrix zu bekommen. Vllt kennt ihr eine Möglichkeit.

Vielen Dank
Hexenkoenig

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

7

13.12.2009, 13:47

Du musst das ja nicht in dem Header benutzen. Lagere das doch in die .cpp aus?

8

13.12.2009, 14:02

Wohoooo! Fehler Weg!

Danke Leute,

mit vereinten Kräften hab ichs geschafft,

Quellcode

1
========== Erstellen: 1 erfolgreich, Fehler bei 0, 0 aktuell, 0 übersprungen ==========


von allem ein bischen und vor allem wieder ein bischen schlauer.
Danke Leute, das macht die Sache ab jetzt viel einfacher, ich glaub ich habs verstanden.

(Und ich will sagen, dass in Rekordzeit, supi 1+ mit *^^)
Gruß
Hexenkoenig

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

10

13.12.2009, 14:08

Also

[list]1. Hab ich wie dus gesagt hast alle Funktionen, die irgendeine Externe Abhängigkeit enthalten in eine seperate C++-Datei ausgelager.

2. Die somit überflüssigen Includes durch Forward-Declaration ersetzt

3. Drauf geachtet, dass überal ein #ifndef - #endif steht

4. In den .cpp Dateien dann die benötigten Header eingebunden[/list]
Und schon hats geklappt

Danke!

Werbeanzeige