C++ Problem mit einem konstanten, statischen Array

badday

Commander
Registriert
Sep. 2007
Beiträge
3.023
Moin zusammen,

ich sitze hier seit einiger Zeit vor einem Problem und komme einfach nicht weiter. Folgendes:
Ich habe eine Klasse Script, die enthält als public member
Code:
 const static luaL_Reg mylib [];


Dies wird in der zugehörigen .cpp-Datei folgendermaßen definiert:
Code:
const luaL_Reg  Script::mylib [] =
       {

               {"example", l_example},
                      {NULL, NULL}


           };

Hinweis: bei luaL_Reg handelt es sich um einen Typ von Lua.

Das Problem: Alles wird schön kompiliert und läuft, aber mylib wird einfach nicht befüllt.
Aber warum?

Vielen Dank!

Gruß,

badday
 
Öhm, was genau ist denn eine Konstante? Meine C++ Kenntnisse sind zwar mehr als eingerostet, aber in anderen Sprachen kann der Initalwert für eine Konstante *nur* während der Initialisierung gesetzt werden. Danach nicht mehr. Sonst geht ja auch irgendwie der Sinn einer Konstanten flöten...
 
Ich dachte, es gäbe hier für static eine Sonderregel, mag sein, dass ich falsch liege.
Ich habe nämlich versucht, das ganze direkt zu initialisieren, erhalte dann aber:
Fehler: a brace-enclosed initializer is not allowed here before »{« token
Fehler: ungültige Initialisierung innerhalb der Klasse des statischen Datenelements vom nicht eingebauten Typen »const luaL_Reg []«
Ich habe dann anch dieser Fehlermeldung gesucht und bin auf folgendes gestoßen:
http://bytes.com/topic/c/answers/624119-how-do-you-declare-use-static-constant-array-inside-class
Soweit ich das sehe, entspricht das meiner obigen Idee.

Wenn ich z. B. versuche, das ganze in die Header-Datei zu packen, so erhalte ich einen Linker-Fehler... Dieser Linker-Fehler geht auf eine doppelte Definition zurück und zwar einmal in script.o und einmal in mainwindow.o, wo ich ein Klassen-Objekt erstelle:
script.o:(.rodata+0x60): multiple definition of `Script::mylib'
mainwindow.o:(.rodata+0x100): first defined here
collect2: ld gab 1 als Ende-Status zurück

@Blitzmerker: Der Vorschlag mit der Elementinitialisierungsliste scheint einleutend zu sein, allerdings scheint er nicht zu funktionieren:

Script::Script(): mylib (luaL_Reg[] { {"example", l_example}, {NULL, NULL} })
{
//...
}
resultiert in:
script.cpp: In constructor »Script::Script()«:
script.cpp:12: Fehler: »const luaL_Reg Script::mylib []«« ist ein statisches Datenelement; es kann nur bei seiner Definition initialisiert werden
script.cpp:12: Fehler: expected primary-expression before »[« token
script.cpp:12: Fehler: expected primary-expression before »]« token


Habe ich irgendetwas falsch gemacht oder hat jemand eine andere Idee?

Vielen Dank.

Gruß,

badday
 
Hm... Ich wollte es eigentlich schon statisch machen, aber gut. Ich habe es anders versucht:
Script::Script(): mylib (luaL_Reg[] { {"example", l_example}, {NULL, NULL} })
{
//...
}
resultiert nun in:
script.cpp:12: Fehler: expected primary-expression before »[« token
script.cpp:12: Fehler: expected primary-expression before »]« token

Wo liegt hier das Problem und gibt es keine Möglichkeit, das ganze als const und static zu definieren?

Vielen Dank!


Gruß,

badday
 
Sorry, aber was genau meinst du mit "Was passiert mit ...luaL_Reg() []..."?
Also ich benutze es, um es in einer anderen Funktion, die im Konstruktor der Klasse aufgerufen wird, für Lua zugänglich zu machen mit:
luaL_register(L, "mylib", mylib);

Vermutlich habe ich dich falsch verstanden, sry.

Gruß,

badday
 
Ich wollte damit auf den Fehler eingehen (exepcted primary expression).
Also ich hab mich jetzt mal rangesetzt und ein bisschen rumgespielt, von "geht nicht" bis "Klammer fehlt" hab ich alle Fehlermeldungen erhalten :) .

Aber:
Deine erste Lösung funktioniert bei mir.
Wie "prüfst" du, ob mylib mit Daten gefüllt ist? (Du musst es natürlich instanzieren mit mylib a;blah(a);).
 
Sorry, aber ich weiß nun nicht was du meinst^^
Was ist die "erste Lösung"?
Was meinst du mit mylib a;blah(a)?

Das zweite erledigt sich vermutlich, wenn ich weiß, was du beim ersten meinst^^

Gruß,

badday
 
Also die allererste Sache, die du versucht hast, deine erste Post, mit dem deklarieren in der Klasse und dann definieren in der .cpp Datei hat es bei mir funktioniert.

Wenn du dann diesen Wert abfragst, musst du dafür die lasse instanziiern.
Also
Code:
//Richtig
luaL_Reg a;
use(a.val);
//Falsch
use(luaL_Reg::val);

Ich hoffe jetzt ist es klar :) .
 
Hm...

Du meinst also, dass ich im Konstruktor von Script mylib instanziieren sollte?

Script::Script()
{
Script::mylib;
//...


}

Ich fürchte ich habe nicht ganz verstanden, auf was du hinaus willst, sry.

Gruß,

badday
 
Als ich geschwind ne testklasse geschrieben hab, da hat alles einwandfrei funktioniert.
Daher denke ich, dass es sein kann, dass du bei der Verwendung vielleicht ein Fehler gemacht hast und es eigentlich schon funktioniert.
Code:
class Script
{...
};
Script::mylib[]...;
int main()
{
Script a;
foo(a.mylib);
}
 
Ja, ich denke auch, das das Problem irgendwo in der Verwendung etc. liegt.
Allerdings weiß ich nicht, wo genau. Hier mal mein aktueller Stand:

script.h
Code:
class Script
{
public:
  static const luaL_Reg  mylib [] ;
//...
private:
 static int l_example(lua_State *L) //wird Element in mylib
    {
        double s = lua_tonumber(L, 1);
        lua_pushnumber(L, sin(s));
        return 1;

    }
};

script.cpp

Code:
Script::Script()
{


    L =  luaL_newstate();
      luaopen_mylib(L);
    luaL_openlibs(L);


}


const luaL_Reg  Script::mylib [] =
       {

               {"example", l_example},
                      {NULL, NULL}


           };


int Script::luaopen_mylib (lua_State *L)
{
    luaL_register(L, "mylib", mylib);
    return 1;
}; //Zeile 257

mainwindow.cpp

Code:
//...
 Script sinus;
  ui->lineEdit_2->setText(sinus.exec(ui->lineEdit->text(),"sinusC.lua", "getsin"));
//...
Wenn ich das ganze im Debugger laufen lasse, so kann ich sehen, dass mylib nicht befüllt wird. Ich frage mich nur, warum? Das erste was gemacht wird scheint
0 global constructors keyed to _ZN6ScriptC2Ev() script.cpp 257
zu sein.
Folglich wird bei luaL_register eine leere "mylib" registriert. Aber warum?

Vielen Dank, Blitzmerker, dass du soviel Geduld mit mir hast. Aber ich mache das nicht extra;)

Gruß,

badday
 
Ich kann halt teilweise nur raten, weil ich die lua-lib nicht drauf hab.
Aber könnte es mit dem Default-Konstruktor zusammenhängen?
Oder was passiert, wenn du bei der Deklaration die const und static vertauschst? (Also statt static const, const static).
Es sind nur Vermutungen, ich bin langsam mit meinem Latein am Ende.

(Aber vielleicht fällt den anderen hier im Forum noch was ein.)
 
Oder was passiert, wenn du bei der Deklaration die const und static vertauschst? (Also statt static const, const static).
Scheint nichts zu ändern.
Aber könnte es mit dem Default-Konstruktor zusammenhängen?
Ich wüsste nicht, inwiefern. Also ich meine Wenn ein Objekt der Klasse erstellt wird, wird doch der Konstruktor ausgeführt aber auch alle Elemente angelegt, oder? Dann würde ja auch das statische Array initialisiert werden.
Er beschwert sich ja auch nicht, dass etwas nicht stimmen würde (wie z. B. das etwas nicht definiert sei etc...
Es wird aber offenbar (laut Debugger) nie initialisiert, andererseits wird dort am Anfang angehalten, wenn ich einen Haltepunkt setzte. Es muss also irgendwo ein Fehler sein, der dazu führt, dass das ganze nicht initialisiert wird. Wenn ich z. B. im default-Konstruktor folgendes einfüge:
so sagt er mir auch:
Warnung: statement hat keinen Effekt

Aber: Warum wird das Array nicht initialisiert?

Gruß,

badday
 
Ich habe einfach mal folgendes ausprobiert:
Header:
Code:
   luaL_Reg  mylib [] ;
.cpp:
Code:
Script::Script()
{
    luaL_Reg mylib [] =
           {

                   {"example", l_example},
                          {NULL, NULL}


               };
    L =  luaL_newstate();
      luaopen_mylib(L);
    luaL_openlibs(L);
}

Nun wird mylib befüllt, allerdings nicht das aus der Klasse (!?). Sondern eines wird neu definiert.
Aber eigentlich bin ich doch im Namensbereich der Klasse? Ich verstehe das nun wirklich nicht mehr. Das angehängte Bild zeigt, was mein Debugger sagt.



Gruß,

badday


EDIT:
Code:
Sonst ist mir noch eingefallen, was passiert, wenn du das static bei der Funktion wegmachst, weil ein statischer Rückgabeparameter macht eig. kein Sinn.
Was meinst du mit "Funktion"?
Die Initialisierung mit der Syntax scheint eigentlich zu passen (oder würde es sonst das oben befüllen?).

Ich weiß echt nicht mehr weiter....:confused_alt::confused_alt::confused_alt:
 

Anhänge

  • Debugger.jpg
    Debugger.jpg
    14 KB · Aufrufe: 143
Zuletzt bearbeitet:
Meinst du mit "Header den "Innenteil" der Klasse?
Lass das "luaL_Reg" weg, du hast mylib schon definiert, du kannst auch "this->mylib" schreiben.

Also:
Code:
Script::Script()
{
    this->mylib  =
           {

                   {"example", l_example},
                          {NULL, NULL}


               };
    L =  luaL_newstate();
      luaopen_mylib(L);
    luaL_openlibs(L);
}

Bei dem static mein ich das "static int l_example(...);"
 
So, nun scheint es zu gehen. Ich habe nun einfach in der Deklaration des Arrays eine Größe angegeben, den this-Zeiger benutzt (wie du geschrieben hast) und schon wird es befüllt.
Das reicht mir derzeit, jetzt kann ich weitermachen.

Nochmal ein herzliches Dankeschön an Blitzmerker, du hast mir wirklich sehr geholfen.

Gruß,

badday
 
Zurück
Oben