[C++] Funktionszugriffe

WiZdooM

Erfahrenes Mitglied
Hallo

Ich entwickle ein Plug-In für Cinema4D, aus organisatorischen Gründen bin auch zwei *.cpp dateien angewiesen. In der einen *.cpp erstelle ich quasi mein Objekt und weise ihm ein Tag, dass ich der zweiten *.cpp erzeuge zu.
Dieses Tag besitzt nun Buttons. Meine Frage ist jetzt folgende: Wie kann ich die Funktionen aus der ersten *.cpp innerhalb meiner Button-Befehle aufrufen.
Generell gefragt: Wie kann man Funktionen für mehrere *.cpps verfügbar machen

Ich habe versucht, sämtliche Funktionen in eine Headerdatei auszulagern, doch bekomme ich da den allseits beliebten LNK2001 Error für "unresolved external symbols" für all meine deklarierten Variablen.
Mir fehlt leider die Programmiererfahrung bezüglich der Programmierung über mehrere Dateien...

Grüße
WiZdooM
 
C/C++ Funktionen bestehen ja bekanntermaßen aus den zwei Komponenten Deklaration und Implementation, wobei man erstere zweckmäßigerweise in eine eigene .h-Datei (Header) schreibt. Den Header kann man nun in alle .cpp includen, die die entsprechenden Funktionen verwenden wollen. Enthält eine .cpp Datendefinitionen, die auch woanders verwendet werden sollen, kann man diese mit dem Schlüsselwort "extern" bekannt machen.

Gruß
MCoder
 
Okay, verstehe ich das dann so richtig ?
Code:
//myHeader.h
extern void Refine(INT, INT);

//file1.cpp
#include myHeader.h
class myClass1{
      void Refine(INT v, INT l){
             //Tue etwas
      }
};

//file2.cpp
#include myHeader.h
class myClass2{
     Refine(4,12);
};
 
Bei Klassen gehören die Klassendeklarationen in den Header...
C++:
// myclass1.h
class myClass1
{
public:
    void Refine(INT c INT i);    
};
... und die Implementierung üblicherweise in die .cpp (Man kann die Implementierung auch mit in den Header schreiben, das wird aber in der Regel nur bei kurzen Codeabschnitten gemacht)
C++:
// myclass1.cpp
#include "myclass1.h"

void myClass1::Refine(INT c INT i)
{
    // ...
}
Wenn du eine Methode aus einer Klasse verwenden willst, musst die Klasse vorher erst instanziieren.
C++:
#include "myclass1.h"

...

myClass1 oMyClass1;
oMyClass1.Refine(4, 12);
Gruß
MCoder
 
Vielen Dank für die Richtigstellung.
Bei komplexeren Strukturen bedeuted das aber, dass sämtliche Funktionsaufrufe und deren Funktionsaufrufe die innerhalb von Refine erfolgen, auch herausgezogen werden müssten. Gleiches gilt für Variablen die von mehreren Funktionen genutzt werden, richtig ?

Ich frage deshalb, da ca 90% aller verwendeten Funktionen innerhalb meines C4D-Plug-Ins rekursiv untereinander aufgerufen wird...
 
Zuletzt bearbeitet:
Ich bin mir nicht ganz sicher, ob ich deine Frage richtig verstanden habe.

Da du ja offensichtlich mit Klassen arbeitest (OOP) brauchst du von den betreffenden Klassen eine Instanz, um auf die darin befindlichen Methoden (Funktionen) und Daten zugreifen zu können. Innerhalb von "Refine" oder innerhalb der Klasse, die "Refine" enthält, müsste also ein Objekt (Instanz) anderer Klassen erzeugt werden, mit dessen Methoden du arbeiten willst.

Gruß
MCoder
 
Hi MCoder,

ja im Prinzip hast du recht.

Ich fange mal vorne mit der Erklärung an.
Das Plugin-SDK für C4D erlaubt nicht, innerhalb einer CPP ein Polygonobjekt über Menüaufruf zu erstellen, und dabei gleichzeitig ein eigenes Tag-Objekt zu definieren und zu erzeugen um dieses dann dem Polygonobjekt zuweisen zu können, dass dann als Kontrollobjekt funktioniert.
Das macht zwei cpps nötig (oder besser gesagt zwei verschiedene Plugins in einem Paket)

Meine Polygonobjekt.cpp hat bisher ungefähr den folgenden Aufbau gehabt:
Code:
class 1{
     //libnoise berechnung
};

class 2 : public CommandData{
     INT Funktion1(INT v){
           // einige Anweisungen
           c= INT Funktion 2 (INT v);
           return c;
     }
     INT Funktion 2(INT v){
           // einige Anweisungen
          return x;
     }
     INT Funktion3(INT v){
           // einige Anweisungen
           c= INT Funktion 2 (INT v);
           return c;
     }
     INT Funktion4(INT v){
           // einige Anweisungen
           c= INT Funktion 2 (INT v);
           return c;
     }

     Refine(INT v, INT level) {
           if(level > 0)
           level--;
                  Refine(Funktion1(v),level);
                  Refine(Funktion3(v),level);
                  Refine(Funktion4(v),level);
          }
     }
};

Wenn ich nun Refine in der plugintag.cpp ausführen will und das wie oben beschrieben mache (im Header deklarieren) kennt natürlich classX::Refine die class2 Funktionen nicht mehr. D.h. ich muss diese auch im Header deklarieren, genauso wie alle Variablen die sie zusammen benutzen, solange sie nicht strikt lokal sind.

Ich habe das mal gemacht, Compiler und Linker sagen okay. Aber leider schmiert mir das Plugin bei der Ausführung aufgrund eines Speicherzugriffsfehler beim Polygonobjekt ab. Das Objekt wurde im vorfeld belegt ehe ein lesender Zugriff erfolgt.

Grüße
WiZdooM
 
Hallo WiZdooM,

der Plugin-Mechanismus von C4D ist mir ziemlich fremd. Da gibt des doch bestimmt irgendwelche Vorgaben, mit denen die Plugins ihre Funktionalität nach "draussen" zu präsentieren haben?. Mit welchen Werkzeug entwickelst du denn die Plugins und welche Form hat ein fertiges Plugin (DLL, EXE, LIB, OBJ)?

oder besser gesagt zwei verschiedene Plugins in einem Paket
Was ist hier mit einem "Paket" gemeint? Ist das ein Projekt?

Meine Polygonobjekt.cpp hat bisher ungefähr den folgenden Aufbau gehabt:
Dieser Code gehört aber in eine "Polygonobjekt.h". Die .cpp wäre dann nicht nötig.

Ein probates Mittel, um Klassenmethoden ohne spezielle Objektinstanz verwenden zu können, ist sie statisch zu machen:
C++:
// Polygonobjekt.h
class 2 : public CommandData
{
    ...

     static void Refine(INT v, INT level)
     {
           ...
     }

    ...
};

//////////////////////////////////////////////////////////
// ... und irgendwo anders verwenden

#include "Polygonobjekt.h"

...

class2::Refine( ... );
Gruß
MCoder
 
Hi MCoder,

der Plugin-Mechanismus von C4D ist mir ziemlich fremd. Da gibt des doch bestimmt irgendwelche Vorgaben, mit denen die Plugins ihre Funktionalität nach "draussen" zu präsentieren haben?. Mit welchen Werkzeug entwickelst du denn die Plugins und welche Form hat ein fertiges Plugin (DLL, EXE, LIB, OBJ)?

Von Maxon wird empfohlen mit Visual Studio zu entwickeln, wobei ich auch schon gesehen habe, dass Leute mit Borland C++ Plugins geschrieben haben. Ich selbst nutze die VC++ Express 2008 dafür.

Was ist hier mit einem "Paket" gemeint? Ist das ein Projekt?
Innerhalb einer Solution werden alle *.cpp zu einer *.cdl zusammengeführt. Die *.cdl entspricht dann einer *dll. Das Hauptproblem ist, dass das SDK von C4D zwar die Syntax und Semantik von C++ verwendet, aber die Dokumentation der Funktionen weit ab von dem ist, womit man effizient arbeiten kann. Es ist sprichwörtliches "try-and-error"-Gewurstel.

Innerhalb meiner *.cdl verwende ich zwei Plug-In-Typen. Ein soganntes Command-Plugin, mit dem ich über die Menüstruktur von C4D anstoßen kann, dass eine Anzahl von Berechnungen auf einem Polygonobjekt erfolgen und dieses dann dargestellt wird. Der andere Typ ist ein sogenanntes Tag-Plugin, was mir eine Art Controller für mein Polygonobjekt darstellen soll, mit dem ich einen einzigen weiteren Berechnungsschritt auf das Objekt durchführen lassen will.

Ein probates Mittel, um Klassenmethoden ohne spezielle Objektinstanz verwenden zu können, ist sie statisch zu machen:

Wenn ich mich noch recht erinnere, müssen ja dann alle aus der statischen Methode heraus verwendeten Funktionen und Variablen ebenfalls statisch gemacht werden, richtig ?! Oder zumindest über die Hauptklasse instanziiert werden.

Schönen Sonntagsgruß
WiZdooM
 
Zuletzt bearbeitet:
Wenn ich mich noch recht erinnere, müssen ja dann alle aus der statischen Methode heraus verwendeten Funktionen und Variablen ebenfalls statisch gemacht werden, richtig ?!
Das ist richtig. Bei der statischen Geschichte vermute ich allerdings dann auch Probleme bei C4D.
Evt. könntest du eine globale Instanziierung versuchen:
C++:
// Polygonobjekt.h
class2 myClass2;

class class2 : public CommandData
{
    ...
};
 
//////////////////////////////////////////////////////////
// ... und irgendwo anders verwenden
 
#include "Polygonobjekt.h"
 
myClass2.Refine( ... );
Gruß
MCoder
 
Zurück