Forum: PC-Programmierung Visual Studio erlaubt keine Zeiger auf eine C++/CLI-Verweisklasse!


von B. P. (skorpionx)


Lesenswert?

Ich versuche ein Programm von C++ Builder auf Microsoft Visual Studio zu
überschreiben.

Das läuft in C++ Builder ohne Fehler:
VarBesch(&i,z,0,VarInfo,"[Form->MinimumPixelE→Text]", 
(DWORD)Form1->MinimumPixelE,EDITEXT);

Im Visual Studio Microsoft:
VarBesch(&i, z, 0, VarInfo, 
"[MinimumPixelE->Text]",(DWORD)this->MinimumPixelE->Text, EDITEXT);

bringt Fehler:
Ungültige Typkonvertierung.
"Typumwandlung": "System::String ^" kann nicht in "DWORD" konvertiert 
werden.

Weitere Test haben das ergeben:
System::Windows::Forms::CheckBox  *gg;      //← Fehler!
   gg = this→KreisZu;
*E1986:   ein normaler Zeiger auf eine C++/CLI-Verweisklasse oder 
-Schnittstellenklasse ist nicht zulässig.*

Also: C++/CLI erlaubt „keine normale Zeiger auf eine
C++/CLI-Verweisklasse oder -Schnittstellenklasse“ Gibts es
auch „nicht normalen Zeiger“... ? Das Bedeutet dass
Visual Studio keine Zeiger auf eine C++/CLI-Verweisklasse
erlaubt!
Ich habe eine Frage an Microsoft Entwickler:
1. Passiert das, dass anders technisch nicht möglich wäre.
2. Oder absichtlich wurde die Begrenzung eingeführt mit der
  Begründung:„sicheres Programmieren".
Veganen essen kein Fleisch und das geht mich nicht an. Aber
manche Veganen wollen anderen Menschen das Essen von Fleisch
(auch Milchprodukten…) verbieten!
C++ Builder hat keine solchen Begrenzungen und nach vielen
Jahren ist weiter beliebt und effektiv! In 80. und 90.
Jahren 20. Jahrhundert kamen Schulabsolventen In Betrieben
mit Pascal kenntnissen. Professoren in Schulen haben nur
Pascal gelernt… In Betrieben mussten Sie aber in „C“
programmieren. Pointer Akrobatik war in Softentwicklung
notwendig. Pascal hat mit „C“ verloren!

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

- Wie sind die Parameter von "VarBesch(...)" deklariert?
- Von welchem Type ist "Form1->MinimumPixelE"?
- Von welchem Type ist "this->MinimumPixelE->Text"?

Von Zeigern ist da höchstens "&i" erkennbar, alles andere wäre für uns 
eher geraten.

von B. P. (skorpionx)


Lesenswert?

Irgend W. schrieb:
> - Wie sind die Parameter von "VarBesch(...)" deklariert?
> - Von welchem Type ist "Form1->MinimumPixelE"?
> - Von welchem Type ist "this->MinimumPixelE->Text"?

Das it nicht wichtig. Das habe im Grrif.
Das ist wichtig:
Weitere Test haben das ergeben:
System::Windows::Forms::CheckBox  *gg;      //← Fehler!
   gg = this→KreisZu;
E1986:   *ein normaler Zeiger auf eine C++/CLI-Verweisklasse oder
 Schnittstellenklasse ist nicht zulässig.*

von Hans-Georg L. (h-g-l)


Lesenswert?

B. P. schrieb:
> Ich versuche ein Programm von C++ Builder auf Microsoft Visual Studio zu
> überschreiben.
>
> Das läuft in C++ Builder ohne Fehler:
> VarBesch(&i,z,0,VarInfo,"[Form->MinimumPixelE→Text]",
> (DWORD)Form1->MinimumPixelE,EDITEXT);
> System::Windows::Forms::CheckBox  *gg;      //← Fehler!
>    gg = this→KreisZu;
> *E1986:   ein normaler Zeiger auf eine C++/CLI-Verweisklasse oder
> -Schnittstellenklasse ist nicht zulässig.*
>
> Also: C++/CLI erlaubt „keine normale Zeiger auf eine
> C++/CLI-Verweisklasse oder -Schnittstellenklasse“ Gibts es
> auch „nicht normalen Zeiger“... ?

Ja, nennt sich sharedPointer (smartpointer) und der enthält den 
"normalen" Pointer bzw eine Referenz auf den String und kann ihn löschen 
wenn der Referenzzähler auf 0 ist).
-> https://en.cppreference.com/w/cpp/memory/shared_ptr

von Re (r42)


Lesenswert?

B. P. schrieb:
> VarBesch(&i, z, 0, VarInfo, 
"[MinimumPixelE->Text]",(DWORD)this->MinimumPixelE->Text, EDITEXT);
>
> bringt Fehler: Ungültige Typkonvertierung.
> "Typumwandlung": "System::String ^" kann nicht in "DWORD" konvertiert

Mag es sein, dass DWORD als 32-Bit-Wert definiert ist, nun aber das 
ganze für ein 64-Bit-Target compiliert wird und der Zeiger viel zu groß 
ist?


B. P. schrieb:
> Gibts es auch „nicht normalen Zeiger“... ?

Seit C++11, freilich: std::shared_ptr<>, std::weak_ptr<>, 
std::unique_ptr<>. Letztere sind vom Footrprint her das Pendant zu 
Raw-Pointern.

> [C++/CLI-Verweisklasse]

Die sind, soweit ich das überblicke, ein Brückenschlag zwischen C++ und 
den gemanagten Ressourcen von dot-NET. Dass die zu diesem Zweck auf 
C++-Seite  auch mit gemanagten Zeigern betan werden wollen, ist 
irgendwie einleuchtend.


B. P. schrieb:
> Aber manche Veganen wollen anderen Menschen das Essen von Fleisch
> (auch Milchprodukten…) verbieten!

[MSVC-C++/CLI] ... wer in ein veganes Restaurant geht, kann sich 
schwerlich darüber aufregen, dass dort der Wunsch nach Fleisch auf 
Ablehnung stößt. Letzteres gibt es dann im Steakhouse.


HTH (re)

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Was ist denn eine "Verweisklasse"?

Re schrieb:
> B. P. schrieb:
>> Aber manche Veganen wollen anderen Menschen das Essen von Fleisch
>> (auch Milchprodukten…) verbieten!
>
> [MSVC-C++/CLI] ... wer in ein veganes Restaurant geht, kann sich
> schwerlich darüber aufregen, dass dort der Wunsch nach Fleisch auf
> Ablehnung stößt. Letzteres gibt es dann im Steakhouse.

Mit anderen Worten: Wenn dir die Einschränkungen, die dir das .net-Zeugs 
mit "C++/CLI" auferlegt, nicht magst, dann nimm halt echtes C++.

von B. P. (skorpionx)


Lesenswert?

Hans-Georg L. schrieb:
> Ja, nennt sich sharedPointer (smartpointer) und der enthält den
> "normalen" Pointer bzw eine Referenz auf den String und kann ihn löschen
> wenn der Referenzzähler auf 0 ist).
> -> https://en.cppreference.com/w/cpp/memory/shared_ptr

Zitat (Auszug...)vom pdf-Buch von Prof.Richard Kaiser:
"int* p=0; // p zeigt nicht auf einen reservierten
// Speicherbereich
Bei einem Handle muss man dafür nullptr verwenden:
int^ h=nullptr; // h zeigt auf keinen Wert"

Das bringt schon keinen Fehler:

System::Windows::Forms::CheckBox^ x = nullptr;

Also einen nullptr kann ich definieren. Was kann man damit
weiter machen...dann... sehe ich noch...

von B. P. (skorpionx)


Lesenswert?

Noch besser:
System::Windows::Forms::CheckBox^ x = nullptr;
  x = this->Dreh90Grad;
Das wir auch akzeptiert!

von Harald K. (kirnbichler)


Lesenswert?

Würdest Du den C++-Compiler verwenden, hättest Du das Problem nicht. 
C++/CLI ist kein C++, sondern eine Microsoft-Perversion für das 
.Net-Geraffel.

Visual Studio kommt aber auch mit einem richtigen, nativen C++-Compiler, 
und der ist a) standardkonform, b) ziemlich aktuell und kann c) echte 
C++-Programme übersetzen.

von Christian R. (supachris)


Lesenswert?

Harald K. schrieb:
> Würdest Du den C++-Compiler verwenden, hättest Du das Problem
> nicht. C++/CLI ist kein C++, sondern eine Microsoft-Perversion für das
> .Net-Geraffel.
> Visual Studio kommt aber auch mit einem richtigen, nativen C++-Compiler,
> und der ist a) standardkonform, b) ziemlich aktuell und kann c) echte
> C++-Programme übersetzen.

Dann gibt's aber kein Windows Forms, und die MFC ist nicht in der 
kostenlosen Version drin.
Was spricht gegen natives C#? Geschwindigkeit? Da könnte man den 
kritischen Code immer noch in C++ schreiben und als DLL einbinden.

von Harald K. (kirnbichler)


Lesenswert?

Christian R. schrieb:
> Dann gibt's aber kein Windows Forms, und die MFC ist nicht in der
> kostenlosen Version drin.

Dann nimmt man halt was anderes; wxWidgets ist in der Struktur der MFC 
ähnlich und hat den Vorteil, sogar auf anderen Betriebssystemen nutzbar 
zu sein. Keine Abhängigkeit von einer nur von Microsoft unterstützten 
Sprache und/oder Entwicklungsumgebung.


Warum eigentlich musste der C++-Builder verlassen und das Projekt 
"portiert" werden?


Christian R. schrieb:
> Was spricht gegen natives C#?

Schon wieder 'ne andere Programmiersprache, und trotzdem mit dem 
.Net-Geraffel als Unterbau. Warum dann nicht gleich VB.net nutzen?

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Christian R. schrieb:
> und die MFC ist nicht in der
> kostenlosen Version drin.

Ist in der Community Edition dabei.

Oliver

von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

using namespace System;
using namespace System::Windows::Forms;

Zitaten:

Namespaces werden verwendet, um Code in logischen Gruppen zu 
organisieren und Namenskonflikte zu vermeiden, die insbesondere dann 
auftreten können, wenn die Codebasis mehrere Bibliotheken enthält. Alle 
Bezeichner im Gültigkeitsbereich des Namespaces sind ohne Qualifizierung 
füreinander sichtbar.

Die Variante mit using namespace sollte üblicherweise nur innerhalb von 
Funktionen genutzt werden, da bei Verwendung im globalen Namensraum das 
ganze Konzept der Namensräume obsolet wird. In gedruckten Büchern wird 
es gern global verwendet, da dies etwas Platz spart und der in solchen 
Büchern knapp ist.


"using namespace std" braucht man, um das Namespace-Konzept von C++ 
ad-absurdum zu führen. Namespaces dienen dazu, Namensbereiche zu 
trennen. Mit diesem unsäglichen "using namespace" wird genau das wieder 
aufgehoben. Oder anders ausgedrückt: Laßt es einfach weg und schreibt 
std::string, std::cout, std::endl usw.

using namespace ? könnte jemand das logisch erklären...

von B. P. (skorpionx)


Lesenswert?

Zitat:
Da nicht auszuschließen ist, dass zwei unabhängig voneinander 
entstandene Quelltexte die gleichen Namen verwenden, wurde in C++ der 
Namensraum eingeführt. Damit können Deklarationen und Definitionen unter 
einem Namen zusammengefasst und gegen andere Namen abgegrenzt werden.

von B. P. (skorpionx)


Lesenswert?

Das klingt vernünftig:
macht all das, was im Namensraum  enthalten ist und durch Header bereits 
eingebunden wurde, im aktuellen Namensraum bekannt. ( Funktionen, Typen, 
... )

In meinem Entwurf von Forms sehe ich keine #include
von diesem System...:
namespace $safeprojectname$ {
  using namespace System;
  using namespace System::ComponentModel;
  using namespace System::Collections;
  using namespace System::Windows::Forms;
  using namespace System::Data;
  using namespace System::Drawing;
Das müsste auf einer anderen Stelle (für mich nicht sichtbar 
passieren...)
Das namespace ist eine Art von Erinnerung...?

von Re (r42)


Lesenswert?

B. P. schrieb:
> using namespace ? könnte jemand das logisch erklären...

Ein Zweck von "using namespace" ist u.a., den Bestand an qualifiziertem 
(oder sogar zertifiziertem) Legacy-Code, bei denen die Funktionen der 
Standard-Library oder anderen Bibliothenken noch nicht durch Namensräume 
getrennt gewesen waren, ohne umfangreiche Änderungen mit modernem C++ 
weiterbenutzen zu können,

Dass man in neu geschriebenen oder refaktorierten Code-Zeilen mit 
solchen Mechanismen sehr sparsam umgehen sollte, versteht sich wohl von 
selbst.


Kennst Du https://www.stroustrup.com/tour3.html ?
Da werden viele Deiner Fragen beantwortet.


B. P. schrieb:
> "using namespace std" braucht man, um das Namespace-Konzept von C++
ad-absurdum zu führen.

Das halte ich für maßlos übertrieben. Ja, man sollte es vermeiden. Aber 
Namensräume, die nicht per "using" eingebunden werden, bleiben ja 
weiterhin gekapselt. Nix "ad-absurdum".



B. P. schrieb:
> Zitaten:

Bitte... zu einem Zitat gehört eine Quellenangabe.



HTH (re)

: Bearbeitet durch User
von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

ein Beispiel vom pdf-Buch von Prof.Richard Kaiser:

In C++ kann man die zusammengehörigen Deklarationen dagegen jeweils
in einen eigenen Namensbereich aufnehmen und die Elemente
dann innerhalb des Namensbereichs unter ihrem angemessenen Namen
ansprechen:
namespace Kunden { // Ein sehr einfaches Beispiel
struct Adresse {
// Elemente, die für Kunden notwendig sind
};
const int Max=1000;
Adresse Adressen[Max];
void show(TextBox^ tb)
{ // ...
}
} // end of namespace Kunden
namespace Mitarbeiter {
struct Adresse {
// andere Elemente wie bei Kunden
};
const int Max=5000;
Adresse Adressen[Max];
void show(TextBox^ tb)
{
}
} // end of namespace Mitarbeiter

Außerhalb eines Namensbereichs kann man seine Elemente mit den
Namen des Namensbereichs, dem Bereichsoperator und den Namen des
Elements ansprechen:

void doSomething(TextBox^ textBox1)
{
Kunden::show(textBox1);
Mitarbeiter::show(textBox1);
}

Auf diese Weise lassen sich auch Namenskonflikte zwischen verschiedenen 
Bibliotheken (z.B. von verschiedenen Herstellern) vermeiden

Die C++-Standardbibliothek fasst alle ihre Elemente in den Namensbereich
std. Wenn man diesen Namen nicht für einen eigenen Namensbereich
verwendet (was man nie tun sollte), bekommt man mit den
Namen der Standardbibliothek nie Namenskonflikte.

von Harald K. (kirnbichler)


Lesenswert?

B. P. schrieb:
> void show(TextBox^ tb)

Das ist kein C++, sondern das .Net-Geraffel.

von Christian R. (supachris)


Lesenswert?

Harald K. schrieb:
> B. P. schrieb:
>> void show(TextBox^ tb)
>
> Das ist kein C++, sondern das .Net-Geraffel.

Deswegen ja mein Einwurf, dann könne man gleich C# nehmen, das macht 
dann viele Dinge einfacher. Das managed c++ muss man halt wollen und 
nimmt man eigentlich nur, wenn man unbedingt muss. Z.B. um eine .net DLL 
in ein bestehendes C++ Programm einzubinden. Ohne Not würde ich das 
nicht nehmen, dann lieber alles C++ oder alles C#. Wenn es nur um das 
GUI geht, wurden ja schon Alternativen genannt.

von B. P. (skorpionx)


Lesenswert?

Christian R. schrieb:
> Deswegen ja mein Einwurf, dann könne man gleich C# nehmen

Ich kenne C# nicht. Bei meinem ersten Einsatz in Visual Studio
habe ich schon bemerkt dass Beispiele in C# waren näher in
Programmierung Logik an meinen Erkenntnissen von C++ als C++/Cli.
Das muss ich wirklich überlegen....

von Falk S. (db8fs)


Lesenswert?

Na ja, so schlimm ist das C++/CLI doch nicht. Es setzt aber halt ein 
zweites Objektmodell dem nativen C++-Objektmodell obendrüber - nämlich 
das der .net-Objekte. Vorteile davon sind unter anderem halt ähnliche 
wie anno dazumals für Objective-C++: man kann bestehenden C++-Code 
nehmen, einen .net-Wrapper verpassen und ziemlich schnell integrieren. 
In C# müssteste für jeden nativen C/C++-Funktionsaufruf sonst entweder 
mit COM-INterfaces arbeiten oder eben P/Invoke-Wrapper basteln - die 
bisweilen auch recht lustige und abgefahrene Funktionssignaturen im 
Resultat haben können, pinvoke.net hin oder her.

Im Endeffekt ist einfach ne 2. Abstraktion für Objekte dazugekommen:

- new (C++) vs. gcnew (.net)
- Pointer (* in C++) vs. Handles (^ in .net)
- Referenzen (& in C++) vs. Ref-Handles (% in .net)

Dazu gibts 4 zusätzliche Typen von struct/class-Kombinationen:

- ref class  (.net Klasse, default private, GC)
- ref struct (.net Klasse, default alles public, GC)
- value class (.net Datatype struct, default private)
- value struct (.net Datatype struct, default public)

Die structs in .net sind halt die Teile, die nur bei Konstruktion 
initialisiert werden können.

Als Adapter-Layer für die wechselseitige Interaktion zwischen C++ und 
.net ist das C++/CLI gar nicht soo schlecht. Man muss dann aber auch mit 
ähnlichen Dingen rechnen, wie eben bei .net auch: Assemblyreferenzen 
setzen, GlobalassemblyCache, Nugets usw. usf.

von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

Falk S. schrieb:
> Na ja, so schlimm ist das C++/CLI doch nicht.

Ich bin für C.Auch emotional! C gibst Programmierung Freiheit.
Das Visual Studio muss ich besser kennenlernen.
Bei neuen Sachen um Zeit zu sparen bewegt sich oft man wie
ich das nenne: intuitiv.
Das läuft ohne Fehler:
Sender:
VarBesch(&i, z, 0, VarInfo, "[MinimumPixelE→Text]",
              MinimumPixelE->Text, EDITEXT);

VarBesch(&i, z, 0, VarInfo, "[MinimumPixelE→Text]",
              this->MinimumPixelE, EDITEXT);

Empänger Funktionen:
short VarBesch (unsigned short* i, unsigned short z, char 
MemReservieren,
VarInfo_typ* VarInfo, char* Name,  System::String^ a, char  Art)
{   ...
        VarInfo[*i].TextString = &a;
    ...
 }
short VarBesch(unsigned short* i, unsigned short z, char MemReservieren,
VarInfo_typ* VarInfo, char* Name,
 System::Windows::Forms::TextBox^ a, char  Art)
{    ...
        VarInfo[*i].TextBoxPointer = &a;
    ...
 }

von Oliver S. (oliverso)


Lesenswert?

B. P. schrieb:
> Ich bin für C.Auch emotional! C gibst Programmierung Freiheit.
> Das Visual Studio muss ich besser kennenlernen.

C ist aber jetzt nicht so die Stärke vom MSVC und Visual Studio.

Oliver

von C-hater (c-hater)


Lesenswert?

Oliver S. schrieb:

> C ist aber jetzt nicht so die Stärke vom MSVC und Visual Studio.

Nunja, genausowenig wie relativ schnell und einfach (sogar quasi 
interaktiv) gebastelte mächtige GUIs die Stärke von C sind...

von B. P. (skorpionx)


Lesenswert?

Bingo!:
short VarBesch(unsigned short* i, unsigned short z, char MemReservieren,
VarInfo_typ* VarInfo, char* Name,
 System::Windows::Forms::TextBox^ a, char  Art)
{    ...
        VarInfo[*i].TextBoxPointer = &a;
       (*VarInfo[*i].TextBoxPointer)->Text = " DD";
    ...
 }
Ich kann die einzelnen Elemente von Forms auch beschreiben. Info
über Pointer in VarInfo[];
Das ist das, was ich wollte!. Bei Borland Builder könte ich
alle Pointer durch cast in DWORD umwandeln. Jetzt brauche ich
für jede Art von Pointer eine Funktion. Aber das ist
kein Problem!

Beitrag #7447282 wurde von einem Moderator gelöscht.
von Harald K. (kirnbichler)


Lesenswert?

B. P. schrieb:
> Ich bin für C.Auch emotional! C gibst Programmierung Freiheit.

Aha.

B. P. schrieb:
> short VarBesch (unsigned short* i, unsigned short z, char
> MemReservieren,
> VarInfo_typ* VarInfo, char* Name,  System::String^ a, char  Art)

Das ist kein C und auch kein C++, sondern die von MS verwürgste 
Pseudo-C++-Variante "Managed C++" bzw. "C++/CLI".

Von Freiheit ist das mit Abstand am weitestens entfernt.

von C-hater (c-hater)


Lesenswert?

Harald K. schrieb:

> Das ist kein C und auch kein C++, sondern die von MS verwürgste
> Pseudo-C++-Variante "Managed C++" bzw. "C++/CLI".
>
> Von Freiheit ist das mit Abstand am weitestens entfernt.

Nein, das ist Quatsch.

Das war so ziemlich das Beste, was man machen könnte, um diesen 
unsäglichen Schrotthaufen C++ den Zugang zu in einer prinzipiell viel 
sichereren Sprache verfaßten GUI zu ermöglichen.

Das Konzept ist logisch: GUI = extrem hohe Komplexität = viel 
Möglichkeiten für Programmierfehler. Sehr viele davon können allein 
durch das sehr viel sicherere Sprachkonzept der der .net-Sprachen 
gefangen werden. Dazu kommt dann noch, dass GUI-Entwicklung in einer 
.net-Umgebung sehr viel komfortabler ist.

Ich persönlich nutze den Kram allerdings auch nicht. Nur 
(zähneknirschend) den umgekehrten Weg. Also ausgehend von .net und dann 
Import und Wrapping dieser immanent unsicheren C/C++ -Scheiße. Allein am 
Aufwand, der dazu oft nötig ist, kann man mühelos erkennen, wie 
schlecht dieser Code oft ist, allein schon vom Design her...

von Harald K. (kirnbichler)


Lesenswert?

C-hater schrieb:
> dieser immanent unsicheren C/C++ -Scheiße.

Wenn man zum Programmieren zu doof ist, dann muss man sich so 
ausdrücken. Ist man das nicht, braucht man auch keine 
Programmiersprache, die einem beim Aufs-Töpfchen-Gehen an die Hand nimmt 
und nett Bubu zu einem sagt.

von C-hater (c-hater)


Lesenswert?

Harald K. schrieb:

> Wenn man zum Programmieren zu doof ist, dann muss man sich so
> ausdrücken. Ist man das nicht, braucht man auch keine
> Programmiersprache, die einem beim Aufs-Töpfchen-Gehen an die Hand nimmt
> und nett Bubu zu einem sagt.

Tja, so sagte der C/C++ -"Programmierer" und verfasste die nächste 
Sicherheitslücke...

Man braucht sich doch nur die Statistik der Sicherheitslücken anschauen, 
um es ganz klar zu erkennen: die übergroße Mehrheit davon resultiert 
ALLEIN aus dem schwachen bis nicht vorhandenen Schutz vor 
Programmierfehlern in C/C++.

Dabei muß man dann noch etwas differenzieren. C++ hätte theoretisch 
zumindest das Potential gehabt, deutlich sicherer zu werden als C. Hat 
bloß nicht geklappt, weil eben auch C-Code "adaptiert" werden sollte. 
Und damit alle Schweinereien, die C ungestraft erlaubt. Das war das 
vorgeburtliche AUS für die Sicherheit von C++.

Dazu kommt dann noch die "UB"-Thematik. Wenn etwas "UB" ist, dann hat 
der Compiler zuverlässig zu warnen. Alles andere ist systematisch 
falsch. Menschen machen nunmal Fehler. Ein Compiler/eine Sprache muss 
diesem Sachverhalt Rechnung tragen, sonst taugt er/sie nix.

Zumal bei einer Sprache wie C++, deren Dokumentation sich über 
TAUSENDE Seiten erstreckt.

von Sophie T. (sophie_t)


Lesenswert?

C-hater schrieb:
>
> Dabei muß man dann noch etwas differenzieren. C++ hätte theoretisch
> zumindest das Potential gehabt, deutlich sicherer zu werden als C. Hat
> bloß nicht geklappt, weil eben auch C-Code "adaptiert" werden sollte.
> Und damit alle Schweinereien, die C ungestraft erlaubt. Das war das
> vorgeburtliche AUS für die Sicherheit von C++.

Hätte nicht, denn C++ war von Anfang als Erweiterung von C gedacht. Also 
hat man den ganzen Kram aus C adaptiert. Von C++ kommt man auch nicht 
mehr weg. In 40 Jahren C++ ist eine Abhängigkeit entstanden. Haufenweise 
Code Bases sind in C++ geschrieben, rewrites - zu teuer. Stattdessen 
wird C++ regelmäßig geupdated auf Verlangen der Industrie. Der Nachwuchs 
ist auch nicht wirklich da für C++ - zu kompliziert, zu umfangreich. 
Lieber Python lernen und den nächsten KI-Wichs zusammenkopieren.

von Harald K. (kirnbichler)


Lesenswert?

C-hater schrieb:
> Tja, so sagte der C/C++ -"Programmierer" und verfasste die nächste
> Sicherheitslücke...

Wären C und C++ so schlecht, wie Du glaubst, dann gäbe es deutlich mehr 
Sicherheitslücken. Die Sprachen legen nur halt etwas höhere Messlatten 
an die Programmierer, wenn man da billige Deppen frisch von der Uni 
ranlässt, dann kann dabei halt Murks rauskommen.

Millionen von stabil und zuverlässig laufenden in C und C++ entwickelten 
Anwendungen beweisen, daß es anders geht als Du Dir zusammenreimst.

Wieso liest man entsprechendes Gekreische von Dir eigentlich nicht über 
Assembler?

von C-hater (c-hater)


Lesenswert?

Harald K. schrieb:

> Wären C und C++ so schlecht, wie Du glaubst, dann gäbe es deutlich mehr
> Sicherheitslücken.

Unsinn. Die existierenden und immer wieder neu aufpoppenden reichen wohl 
völlig aus, um meine Einschätzung eindrucksvoll zu beweisen.

Zumal: bei genauerer Betrachtung würden sich wohl auch noch mehr finden 
lassen...

> Millionen von stabil und zuverlässig laufenden in C und C++ entwickelten
> Anwendungen beweisen, daß es anders geht als Du Dir zusammenreimst.

Welche? Nenne auch nur eine einzige!

> Wieso liest man entsprechendes Gekreische von Dir eigentlich nicht über
> Assembler?

Weil reiner Assembler natürlich konzeptionell vollkommen unsicher ist. 
Aber: da C Assembler-Teile als integralen Bestandteil enthält, erbt es 
natürlich auch noch deren Unsicherheit! Und C++ wiederum erbt das von C.

Sprich: Wenn man was Sicheres will, sind Assembler, C und C++ tabu.

Wenn man hingegen was Schnelles und Effizientes will (und 
Sicherheitsaspekte eher eine untergeordnete Rolle spielen oder Probleme 
durch die Umgebung (OS) gefangen werden können), ist Assembler das 
Mittel der Wahl.

Was man eigentlich niemals wirklich braucht, ist: C und C++. Es sei 
denn, man will (meistens eher: muss) vorhandenen Code verwenden, der in 
diesen Sprachen geschrieben wurde. Leider ist das aber der Normalfall. 
Mit den bekannten Folgen bezüglich der Sicherheit...

von Harald K. (kirnbichler)


Lesenswert?

Hach, es ist immer wieder schön, Deine Beiträge zu lesen, die von 
gründlicher Ahnungslosigkeit zeugen. Wärest Du Papst, Du würdest ähnlich 
detailliert Stellungen aus dem Kamasutra kritisieren ...

von C-hater (c-hater)


Lesenswert?

Harald K. schrieb:

> Hach, es ist immer wieder schön, Deine Beiträge zu lesen, die von
> gründlicher Ahnungslosigkeit zeugen.

Ah ja. Aber zu einer sachlichen Erwiderung bist du offensichtlich nicht 
in der Lage...

Da fragt man sich dann doch, wo die Ahnungslosigkeit tatsächlich 
residiert...

von Harald K. (kirnbichler)


Lesenswert?

Warum sollte ich auch? Mit Salafisten muss man auch nicht diskutieren.

von B. P. (skorpionx)


Lesenswert?

Ich experimentiere weiter... Ich wollte gerne in der Visual Studio
 klassische Elemente von C++ verwenden. Das brachte eine Menge
 von Fehlermeldungen:
#include <string.h>
#include <stdlib.h>
#include <iostream>
namespace std;
...
{
 string s=“ggg“;
….

Aber das funktioniert!:

#include <string.h>
#include <stdlib.h>
#include <iostream>
//namespace std;
...
{
 std::string s=“ggg“;
….

Also ohne: „namespace std;“ aber explizit (Beispiel…) mit dem präfix 
std:: geht das!

von Rolf M. (rmagnus)


Lesenswert?

B. P. schrieb:
> Das brachte eine Menge von Fehlermeldungen:

Der Compiler sagt aber nicht einfach nur "Fehler", sondern sagt dir, 
was der Fehler ist. Lies die Meldungen und versuche, sie zu verstehen.

B. P. schrieb:
> Also ohne: „namespace std;“ aber explizit (Beispiel…) mit dem präfix
> std:: geht das!

Weil "namespace std;" keinen Sinn ergibt. Du meinstest vermutlich "using 
namespace std;", was man allerdings in der Regel vermeiden sollte, weil 
es dem Sinn von Namespaces widerspricht. Das wurde hier eigentlich alles 
schon erklärt.

: Bearbeitet durch User
von B. P. (skorpionx)


Lesenswert?

Rolf M. schrieb:
> Du meinstest vermutlich "using
> namespace std;

Ja. "using" durch Versehen  gelöscht...

von B. P. (skorpionx)


Lesenswert?

Rolf M. schrieb:
> Der Compiler sagt aber nicht einfach nur "Fehler", sondern sagt dir,
> was der Fehler

Es sind so viele Fehler! Und das sind auch verschiedene Fehler, die
auf die #include Standard Files zeigen. Das muss man verstehen,
dass Visual Studio nicht alles von C++ akzeptiert. Nur manche
Sachen die man mit dem Präfix std:: gekennzeichnet.

: Bearbeitet durch User
von Falk S. (db8fs)


Lesenswert?

B. P. schrieb:
> short VarBesch (unsigned short* i, unsigned short z, char
> MemReservieren,
> VarInfo_typ* VarInfo, char* Name,  System::String^ a, char  Art)

Die Deklaration von VarInfo_typ wär durchaus hilfreich gewesen, auch 
wenns jetzt funktionieren mag.

Harald K. schrieb:
> Das ist kein C und auch kein C++, sondern die von MS verwürgste
> Pseudo-C++-Variante "Managed C++" bzw. "C++/CLI".
>
> Von Freiheit ist das mit Abstand am weitestens entfernt.

Na ja, ECMA-Standard isses ja, gibt halt nur wenig freie Compiler, die 
es können - müsste ja wohl quasi irgendwie über Mono laufen, wenn es 
denn gehen sollte.

Prinzipiell geb ich dir recht: GUI-Elemente würde ich auch nicht 
unbedingt in C++/CLI bauen wollen, da gibts bessere .net-Sprachen für 
sowas.

Zum Zweck der Adaptierung von nativem Code in managed Code, isses ok und 
sogar teilweise eine gute Alternative, weil du eben auch 
C/C++-spezifische Sachen wie Bitfields oder templates damit ansteuern 
kannst. Solche gemangelten Sachen über p/invoke zu machen fände ich noch 
viel schlimmer. Man kann zwar sagen: gut, dann design halt ne gescheite 
C-Export-API für die DLL, die solchen Mist gar nicht erst zulässt. Dafür 
sieht dann dein p/invoke-Wrapper auf C#-Seite auch wieder schrottig aus 
und ist meistens so ein häßliches Konstrukt aus einer statischen Klasse 
- die aber trotzdem dann über das von C aus exportierte void*-Handle 
irgendwo noch Zustand hat. D.h. man frickelt dann 2 Wrapper-Layer in C# 
um eine popelige DLL objektorientiert anzusteuern... (eigentliche Klasse 
+ statische p/invoke-Klasse drunter)

Grosser Nachteil sehe ich allerdings für C++/CLI auch, sobald sowas wie 
CMake ins Spiel kommt - mit dem MSVC hat man zwar wohl theoretisch ne 
Chance und .net Nugets/Referenzen gehen wohl auch mittlerweile, aber so 
richtig geil ist das glaub ich noch nicht.

von Rolf M. (rmagnus)


Lesenswert?

B. P. schrieb:
> Rolf M. schrieb:
>> Der Compiler sagt aber nicht einfach nur "Fehler", sondern sagt dir,
>> was der Fehler
>
> Es sind so viele Fehler!

Es ist sinnvoll, mit dem ersten anzufangen, denn die anderen sind meist 
Folgefehler, weil der Compiler den Faden verloren hat, oder sie dienen 
der Erläuterung des vorherigen Fehlers, indem sie z.B. auf eine für den 
Fehler relevante Stelle im Code verweisen.

> Und das sind auch verschiedene Fehler, die auf die #include Standard
> Files zeigen.

Dann sind diese hoffentlich Tel der oben genannten Erläuterung, denn in 
den Standard-Headern sollten ja keine Fehler sein. Alternativ kann das 
auch durch eigene Header kommen, die vor den Standard-Headern 
eingebunden wurden.

> Das muss man verstehen, dass Visual Studio nicht alles von C++
> akzeptiert.

Das kommt darauf an, wie du es nutzt. Wenn es auf echtes C++ eingestellt 
ist, sollte es das schon auch akzeptieren. Hast du ein Beispiel, was da 
nicht geht?

von Falk S. (db8fs)


Lesenswert?

B. P. schrieb:
> Es sind so viele Fehler! Und das sind auch verschiedene Fehler, die
> auf die #include Standard Files zeigen. Das muss man verstehen,
> dass Visual Studio nicht alles von C++ akzeptiert. Nur manche
> Sachen die man mit dem Präfix std:: gekennzeichnet.

Na ja, die <string.h> sollte eigentlich ja auch was anderes als die 
<string>-Header sein. Im Normalfall sollte nach üblicher C++-Notation 
die <string.h> die <cstring> sein (die solches Zeug wie strcmp, strcat, 
strtok, usw. hält), während <string> und <wstring> halt eben die 
C++-STL-strings in beiden Geschmacksrichtungen verfügbar macht. Lustig 
wirds bei deinem obigen C++/CLI-Beispiel, wo System::String und glaube 
System::SecureString noch dazukommen kann.


U.a. mal noch folgender Tipp: sowas lieber nicht machen:
1
struct Foo
2
{
3
  System::String ^ m_text;
4
5
  Foo() : m_text(gcnew System::String()) { }
6
  
7
  std::string toString() { /*return m_text.<irgendeine fkt, falls es überhaupt geht>* /};
8
9
};

Imho besser wäre: managed Code drumrum, als Member dann aber nur 
native Typen:
1
public ref struct Foo
2
{
3
  Foo() : m_text() {}
4
  ~Foo() { this->!Foo(); } // hier drunter nur natives c++ zeug aufräumen
5
  !Foo() {} // hier drin nur .net zeug aufräumen, wird vom GC aufgerufen
6
7
  std::string m_text;
8
9
  System::String^ toString() { return gcnew System::String(m_text.c_str()); }
10
};

Soll heißen: nicht native Klassen .net Membervariablen halten lassen, 
besser umgekehrt. Begründung: man hat oft keine Möglichkeit, aus den 
.net Klassen native Informationen rauszuziehen. Zusätzlich noch dazu 
kommend: die weniger günstige Variante von oben hat potentiell den 
Nachteil, dass du MemoryLeaks beim Aufruf durch .net kriegen kannst, 
wenn das .net den !Foo-Finalizer aufruft und der nicht gescheit 
implementiert ist. Das Problem mit diesem Disposing haste aber in C# 
wohl auch, C++/CLI hin oder her - ist scheinbar ne übliche 
.net-Interop-Problematik.

von B. P. (skorpionx)


Lesenswert?

Wie kann ich Pointer auf Pointer i Visual Studio definieren:
1
//Pointer auf System::String 
2
//Das funktioniert ohne Fehler
3
System::String^ SysStringPoint;
4
SysStringPoint = MinimumPixelAbstandE->Text;
5
    
6
//Pointer auf Pointer von System::String 
7
System::String^ *SysStringPPoint;  
8
SysStringPPoint = MinimumPixelAbstandE->Text;
9
//Diese Zuweisung wird
10
//nicht akzeptiert.Was muss ich hier ändern 
11
//(Zusatz für Wandlung...)
weiss das jemand...?

von Harald K. (kirnbichler)


Lesenswert?

B. P. schrieb:
> //Pointer auf System::String
> System::String^ SysStringPoint;

Falsch. Das ist kein Pointer. Das ist eine Microsoft-Abartigkeit, die es 
in echtem C++ nicht gibt.

von Roger S. (edge)


Lesenswert?

B. P. schrieb:
>
1
> //Pointer auf Pointer von System::String
2
> System::String^ *SysStringPPoint;
3
> SysStringPPoint = MinimumPixelAbstandE->Text;
4
> //Diese Zuweisung wird
5
> //nicht akzeptiert.Was muss ich hier ändern
6
> //(Zusatz für Wandlung...)
7
>

Um sowas wie ein Pointer zu bekommen muesstest du das pinnen, macht aber 
auf ein Objekt wie System::String kein Sinn.
Wozu meinst du soll ein Zeiger gut sein? Was fuer ein Problem hast du 
mit der .NET referenz?

Hat es einen speziellen Grund warum Du C++/CLI verwendest?
Falls du keinen alten C++ code in der WinForms GUI verwenden musst -> 
kipp das Ganze und wechsle auf C#.

von Sophie T. (sophie_t)


Lesenswert?

Falk S. schrieb:
> Na ja, die <string.h> sollte eigentlich ja auch was anderes als die
> <string>-Header sein. Im Normalfall sollte nach üblicher C++-Notation
> die <string.h> die <cstring> sein

Jein. string.h wäre nicht im namespace std gekapselt und bei cstring 
schon.
Man sollte cstring bevorzugen sonst gibts schnell böse Überraschungen.
Aber warum kein normaler C++ String? string.h ist die C Bibliothek für 
strings :D

von Harald K. (kirnbichler)


Lesenswert?

Sophie T. schrieb:
> string.h ist die C Bibliothek für strings

string.h ist keine "Bibliothek".

von Falk S. (falk_s831)


Lesenswert?

B. P. schrieb:
> Wie kann ich Pointer auf Pointer i Visual Studio definieren:
>
1
> //Pointer auf System::String
2
> //Das funktioniert ohne Fehler
3
> System::String^ SysStringPoint;
4
> SysStringPoint = MinimumPixelAbstandE->Text;
5
>

Ja, SysStringPoint ist initial ein nicht initialisiertes Handle. Quasi 
eine null-Zuweisung in .net. Durch die Zuweisung drunter übergibst du 
dem Handle SysStringPoint das Handle von MinimumPixelAbstandE->Text, was 
seinerseits ein .net-Objekt zu sein scheint (wenn dieser Code bei dir so 
kompiliert - ich kenn ja den Datentyp von MinimuPixelAbstandE nicht, 
nehme aber an, das ist eine Art Textfeld).

>
1
> //Pointer auf Pointer von System::String
2
> System::String^ *SysStringPPoint;
3
> SysStringPPoint = MinimumPixelAbstandE->Text;
4
> //Diese Zuweisung wird
5
> //nicht akzeptiert.Was muss ich hier ändern
6
> //(Zusatz für Wandlung...)
7
>

Das wird nicht funktionieren - niemals ein .net-Handle und einen nativen 
Pointer gleichsetzen. Du kannst keinen Pointer (*) auf ein vom 
.net-Framework verwaltetes Objekt bekommen, weil Pointer unter der 
Kontrolle der C/C++-Runtime sind (z.B. MSVCRT), .net-Gedönse aber halt 
eben im CommonLanguageInterface drinne sind. D.h. soviel wie: es wird 
aus dem .net-Objekt eine Intermediate-Language (IL) wie bei Java erzeugt 
und von einem .net-'VirtualMachine' ausgeführt, welche die IL eben 
selber in nativen Code übersetzt. Und weil du da auch nicht auch nicht 
drumrum kommst, dafür gibst ja C++/CLI - damit du beide Welten verbinden 
kannst.

Was du ja eigentlich bezwecken scheinst, ist es ja, den Text aus dem 
Steuerelement auszulesen. Und dafür musste halt mit Mitteln von C++/CLI 
aus dem .net-Objekt System::String das raus-'marshallen'. Beim Visuellen 
Studio sollte es wohl so ähnlich ausschauen:
1
#include <msclr/marshal_cppstd.h>
2
3
System::String^ text(MinimumPixelAbstandE->Text); 
4
std::string nativeText=msclr::interop::marshal_as< std::string >(text);

Und dann kannste den 'nativeText' mit normalen C++-Mitteln weiter 
verarbeiten. Der umgekehrte Weg sollte einfach über Konstruktor möglich 
sein:
1
MinimumPixelAbstandE->Text = gcnew System::String("Mein Toller Text");

von B. P. (skorpionx)


Lesenswert?

Ich teste Programmierung in C++/CLI mit Forms. Jetzt mache
ich einen Versuch mein altes Programm, das ich unter
C++ Builder geschrieben habe, in Visual Studio
mit Forms zu umschreiben. Am Anfang alle Steuerelemente
von Form (CheckBox ComboBox, TextBox…) sind in einem Array
von diesem Typ angemeldet:
1
typedef struct {
2
    char* Name;
3
        DWORD  Pointer;
4
        System::Windows::Forms::TextBox^  *TextBoxPointer;
5
        System::Windows::Forms::CheckBox^ *CheckBoxPointer;
6
        System::Windows::Forms::ComboBox^* ComboBoxPointer;
7
        char Art;
8
} VarInfo_typ;
Abspeicherung von dem Inhalt von diesen Steuerelementen in
einem File läuft das in einer for-Schleife. Genauso ist es
beim Laden aus einem File.Im C++ Builder brauchte ich sogar
nur DWORD Pointer, weil ich könnte alle Pointertypen von
Steuerelementen in DWORD durch cast umwandeln.
Ich kenne mich absolut nicht mit .NET. Also ^ ist kein
Pointer sondern nur Handle? Könnte man dieses Handle (das
ist auch nur eine Zahl...? ) nicht abspeichern
z.B. in meiner VarIno_typ Structur? Und das später
abzurufen? Vielleicht geht das auch anders...

von Rolf M. (rmagnus)


Lesenswert?

B. P. schrieb:
> Genauso ist es
> beim Laden aus einem File.Im C++ Builder brauchte ich sogar
> nur DWORD Pointer, weil ich könnte alle Pointertypen von
> Steuerelementen in DWORD durch cast umwandeln.

Warum sollte man das machen? Das ist grauenvoll. Es hat schon seinen 
Grund, warum es Pointertypen gibt. Abgesehen davon reicht - wie schon 
gesagt wurde - auf einer 64-Bit-Plattform ein DWORD nicht aus, um einen 
Zeiger zu speichern.

> Ich kenne mich absolut nicht mit .NET. Also ^ ist kein
> Pointer sondern nur Handle? Könnte man dieses Handle (das
> ist auch nur eine Zahl...? ) nicht abspeichern
> z.B. in meiner VarIno_typ Structur? Und das später
> abzurufen? Vielleicht geht das auch anders...

Warum willst du zwanghaft das Typsystem umgehen?

von B. P. (skorpionx)


Lesenswert?

Rolf M. schrieb:
> Im C++ Builder brauchte ich sogar
>> nur DWORD

Rolf M. schrieb:
> Warum sollte man das machen?

In diser Zeiten waren alle Pointer nicht länger als DWORD

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

B. P. schrieb:
> In diser Zeiten
Die Zeiten sind aber schon lange vorbei.

von B. P. (skorpionx)


Lesenswert?

Kaj G. schrieb:
> Die Zeiten sind aber schon lange vorbei.

Das weiß jeder. Die Aussage bringt nichts zur Lösung.
Ich habe schon eine Idee im Kopf, wie ich das lösen kann...
Mit Fehler muss man sich arrangieren...

von Roger S. (edge)


Lesenswert?

B. P. schrieb:
> Am Anfang alle Steuerelemente
> von Form (CheckBox ComboBox, TextBox…) sind in einem Array
> von diesem Typ angemeldet:

Wenn du das willst, dann musst du das in ein ref class/struct packen und 
in einen CLR/.NET container ablegen. Aber wozu soll man das wollen?

> Ich kenne mich absolut nicht mit .NET. Also ^ ist kein
> Pointer sondern nur Handle? Könnte man dieses Handle (das
> ist auch nur eine Zahl...? ) nicht abspeichern
> z.B. in meiner VarIno_typ Structur? Und das später
> abzurufen? Vielleicht geht das auch anders...

Die moeglichkeit besteht mit GCHandle.Alloc() und GCHandle.ToIntPtr().
Das gibt dir ein Zeiger (ein IntPtr, kein DWORD, IntPtr.ToPointer gibt 
dir ein native Zeiger) auf ein beliebiges .NET Objekt. mittels 
GCHandle.FromIntPtr() kommst du vom Zeiger wieder zum .NET Objekt. Ob du 
damit Gluecklich wirst?

Mein Tip an dich:
 - Willst du bei C++ bleiben dann schau dir QT an.
 - Gefaellt dir WinForms, wechsle zu C#
 - Scheust du dich nicht von einer steilen Lernkurve, dann C# mit WPF 
oder Avalonia

Was du dir auf jeden Fall anschauen solltes ist 'data binding'. Das 
koenenen alle genannten GUI frameworks. Ueber Steuerelemente zu 
iterieren und befuellen macht man eigentlich nicht mehr.

von Rolf M. (rmagnus)


Lesenswert?

Roger S. schrieb:
> Aber wozu soll man das wollen?

Das frage ich mich im Bezug auf die ganzen dubiosen Dinge, die er hier 
versucht, schon die ganze Zeit. Dazu sagt er aber nichts. Das ist 
ungefähr so, als ob einer fragt, wie man am geschicktesten mit dem Kopf 
ein Loch in die Wand schlägt.

von Harald K. (kirnbichler)


Lesenswert?

B. P. schrieb:
> Ich teste Programmierung in C++/CLI mit Forms. Jetzt mache
> ich einen Versuch mein altes Programm, das ich unter
> C++ Builder geschrieben habe,

Du wechselst also die Programmiersprache, dessen musst Du Dir sehr 
deutlich bewusst sein.

Der "C++ Builder" verwendete echtes C++, "C++/CLI" ist kein C++, 
sondern eine Microsoft-Speziallösung, um optisch ähnliches wie C++ auf 
den .Net-Unterbau draufzuflanschen.

von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

Meine Übersetzung von Borland Builder in Microsoft Visual
Studio von Microsoft macht Fortschritte.  Mein altes Borlands
Projekt ist hier: Beitrag "PCB von BMP drucken"
MyForm  mit allen Steuerelementen ist schon fertig. Als erste
habe ich die Abspeicherung und Laden von Daten (Parameter)
von  Steuerelementen (TextBox, ComboBox, CheckBox) in Angriff
genommen. Nach dem Start vom Programm werden alle Steuerelemente
mit den Initialisierungswerten vorbesetzt:
1
  Breite->Text = "3.05";
2
   ...
3
   RundungsModusVertikal->SelectedIndex = 2;
4
   ...
5
   Dreh90Grad->Checked = 1;
Danach werden Informationen von allen Steuerelementen über eine
Funktion in VarInfo_typ* VarInfo eingespeichert:
1
VarBesch(&i, z, Mem, VarInfo, "[MinimumPixelE->Text]", TEXT_String);
2
 
3
 VarBesch(&i, z, Mem, VarInfo, "[Spiegeln->Checked]", CHECK_Bool);
4
 
5
VarBesch(&i, z, Mem, VarInfo, "[MM_INCH->SelectedIndex]", COMBO_Zahl);
1
System:String^* pp;
2
    pp = &(thisMinimumPixelAbstandEText);
3
bringt Fehler: Fehler C2102 "&" erwartet L-Wert
Bei Borland Builder könnte ich auch Pointer von allen Steuerelementen
in VarInfo übertragen. Leider unter Visual Studio ist das nicht möglich.

von Falk S. (falk_s831)


Lesenswert?

B. P. schrieb:
>
1
System:String^* pp;
2
>     pp = &(thisMinimumPixelAbstandEText);
3
> bringt Fehler: Fehler C2102 "&" erwartet L-Wert

Na ja, lass doch einfach den * und den & weg und schon geht's.

Warum? Aktuell deklarierst du die Variable als vom Datentyp 
Pointer-auf-.net-Handle. Wie oben schon mal geschrieben ist das halt 
nicht so sonderlich große Idee, weil eben .net das eine (verwaltet übers 
.net-Framework) und C++-Code halt ne andere Sportart ist (nativ 
übersetzt).

Wenn du unbedingt deine Steuerelemente in ne Klasse packen willst, dann 
kannste deinen VarInfo_Typ halt so ändern. Btw. typedefs für structs 
ist in C++ eigentlich nicht unbedingt nötig, du kannst den Namen auch 
hinter's 'struct' schreiben (und das typedef weglassen).

Soll heißen, aus:
1
typedef struct {
2
    char* Name;
3
    DWORD  Pointer;
4
    System::Windows::Forms::TextBox^  *TextBoxPointer;
5
    System::Windows::Forms::CheckBox^ *CheckBoxPointer;
6
    System::Windows::Forms::ComboBox^* ComboBoxPointer;
7
    char Art;
8
} VarInfo_typ;

könnte werden:
1
struct Steuerelemente /* immer noch ungeeigneter Name, aber besser als oben das */
2
{
3
    char* Name = nullptr;
4
    DWORD  Pointer = 0;
5
    System::Windows::Forms::TextBox^  TextBoxPointer;
6
    System::Windows::Forms::CheckBox^ CheckBoxPointer;
7
    System::Windows::Forms::ComboBox^ ComboBoxPointer;
8
    char Art='\0';
9
};

Ist nicht unbedingt direkt jetzt 'schön' weil's ne normale struct ist 
und keine .net-ref-struct, sollte aber gehen. Die Initialisierung deiner 
Steuerelemente (TextBoxPointer, usw.) machste wie oben geschrieben ohne 
& und *.

: Bearbeitet durch User
von B. P. (skorpionx)


Lesenswert?

Falk S. schrieb:
> Die Initialisierung deiner
> Steuerelemente (TextBoxPointer, usw.) machste wie oben geschrieben ohne
> & und *.

Ich habe beide Versionen getestet. Leider ohne Erfolg.
1
 So würde ich einen Pointer (auf Pointer) auf TextBox
2
  bekommen und dann könnte ich TextBox Elemente lesen
3
  und beschreiben. So funkt das bei Borland Builder aber nicht
4
  beim Visual Studio:
5
 System::Windows::Forms::TextBox^  *TextBoxPointer;
6
So bekomme ich nur eine Kopie vom Inhalt vom TextBox:
7
System::Windows::Forms::TextBox^  TextBoxPointer;

von Roger S. (edge)


Lesenswert?

B. P. schrieb:
> Meine Übersetzung von Borland Builder in Microsoft Visual
> Studio von Microsoft macht Fortschritte.  Mein altes Borlands
> Projekt ist hier: Beitrag "PCB von BMP drucken"
> MyForm  mit allen Steuerelementen ist schon fertig.

Wuerde sagen: Hat sich gelohnt, 50% Groessenersparnis mit der neuen 
Technologie...

Wobei, mich wundert jetzt auch nicht mehr die Wahl von WinForms mit 
C++/CLI.

Bist Du zufrieden damit? Moechtest Du ein beispiel wie man das moderner 
gestalten koennte?

: Bearbeitet durch User
von Falk S. (db8fs)


Lesenswert?

B. P. schrieb:
> So bekomme ich nur eine Kopie vom Inhalt vom TextBox:
> System::Windows::Forms::TextBox^  TextBoxPointer;[/c]

Hmm, ok. Ändert sich was, wenn du das machst:
1
System::Windows::Forms::TextBox%  TextBoxPointer;

von B. P. (skorpionx)


Lesenswert?

Um das fehlendes Zugriff über Pointer auf Steuerelemente
umzugehen, habe ich eine Funktion mit switch/case mit der ich 
Korrespondiere von meinen for schleifen zum save und load von
Daten. Manche Teile von Meinem Programm unter Borland Builder
 sind fast gleich und nach kleiner Anpassung direkt
zum Übernehmen. Beispiel:
1
private: System::Void LoadParameter_Click(System::Object^ sender, System::EventArgs^ e)
2
{  HANDLE InDateiHandle;
3
  DWORD  FileInLaengeH, FileInLaenge;
4
  HANDLE StandardHeapHandle;
5
  LPVOID PointerAllocPuff;
6
  String^ MyFileNameString;
7
8
  Meldung2->Text = "";
9
  InDateiHandle = INVALID_HANDLE_VALUE;
10
  PointerAllocPuff = 0;
11
   …………. 
12
MyFileNameString = openFileDialog1->FileName;
13
pin_ptr<const wchar_t > wch = PtrToStringChars(MyFileNameString);
14
InDateiHandle = CreateFile(wch,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

Ich lese das ganze File in Puffer und arbeite nur mit Bytes.
Alle Variablen werden mit ASCII Namen (in Klammer [])
abgespeichert. Beim lesen von File wird nur nach diesen
Namen gesucht.Mit diesem Wirrwarr von tausenden Klassen will
ich nichts zu tun haben. Die Sache ist zu weit gelaufen.
Niemand wagt sich sagen dass der König nackt ist.

von B. P. (skorpionx)


Lesenswert?

Falk S. schrieb:
> Hmm, ok. Ändert sich was, wenn du das machst:
> System::Windows::Forms::TextBox%  TextBoxPointer;

Das werde ich noch testen...

von B. P. (skorpionx)


Lesenswert?

B. P. schrieb:
> Falk S. schrieb:
>> Hmm, ok. Ändert sich was, wenn du das machst:
>> System::Windows::Forms::TextBox%  TextBoxPointer;
>
> Das werde ich noch testen...

Das % Zeichen wird nicht akzeptiert...

von Sven K. (svenk)


Lesenswert?

Hallo B.P.,
darf ich Dich noch mal fragen wieso Du Dir diese Mühe machst ?
Es gibt die C++ Builder Community edition for free. Du darfst halt kein 
Geld damit verdienen bzw Max 5000$.
Hast Du schon mal probiert Deine Projekte/Projekt dort mit der neuen IDE 
zu laden?

Ist nur ein Gedanke …

Gruß Sven

: Bearbeitet durch User
von B. P. (skorpionx)


Lesenswert?

*C++/CLI erlaubt Zeiger auf eine C++/CLI-Verweisklasse
oder -Schnittstellenklasse!*
Man muss das so definieren wie im Beispiel:
1
SauberMinTVor->Text = "321";
2
cli::interior_ptr <System::Windows::Forms::TextBox^> kkk;
3
kkk =  & (System::Windows::Forms::TextBox^)SauberMinTVor;
4
System::Windows::Forms::TextBox^ pp = *kkk;
5
pp->Text = "123";

von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

Pointer auf Felder (TextBox, ComboBox, CheckBox…) könnte ich
in einer Structur speichern.Bei dem Wiederverwenden von
Pointer (im Debug)kommt jedoch zum Fehler. Sehe das Bild.
Hat jemand einen Rat...

von B. P. (skorpionx)


Angehängte Dateien:

Lesenswert?

Nach einer kleinen Änderung kommt jetzt dieser Fehler…
Geschützter Speicher… Aber ich will und muss dort zugreifen..

von B. P. (skorpionx)


Lesenswert?

Das ist so unter C++ Builder von Borland gegangen. Mit Visual
Studio geht das so nicht.Im Visual Studio bekommt man
(intuitives Denken…)nur eine Kopie von Pointer auf einen
Formsfeld auf dem Stack.Zwischenspeicherung vom Pointer auf
Formsfelder in einer Funktion bringt nichts, weil nach dem
Verlassen der Funktion Stack ändert sich.
1
for(i=0;....){
2
VarBesch(B,&i, z, Mem, VarInfo, "[Form1->MinimumPixelE->Text]", *(&SauberMinT), TEXTBOX);
3
VarBesch(B,&i, z, Mem, VarInfo, "[Form1->Spiegeln->Checked]",
4
*(&Spiegeln), CHECKBOX);
5
VarBesch(B,&i, z, Mem, VarInfo, "[Form1->MM_INCH->ItemIndex]",
6
 *(&MM_INCH), COMBOBOX);}
Im „for“ Block werden alle Formsfelder angemeldet. Nach erstem
Durchlauf wird maximale Anzahl von Felder berechnet (==i) und
wird Speicher allokiert für VarInfo. Danach werden alle notwendige
Daten in der Funktion VarBesch()in die VarInfo geschrieben.
Jedes Feld bekam jetzt auch eine Nummer(ErsatzPointer...)
In der Funktion VarBesch() sind die Pointer auf Formsfelder
aktuell und ich Kommuniziere mit diesem „for“ mit Befehlen
zum Lesen oder Beschreiben von Formsfelder. Bei einem neuen
Formsfeld zum Save oder Load wird nur eine neue Meldungszeile
eingeführt.Das alles wäre auch mit „case“ möglich, aber mit viel 
Handarbeit.

von Harald K. (kirnbichler)


Lesenswert?

B. P. schrieb:
> Das ist so unter C++ Builder von Borland gegangen. Mit Visual
> Studio geht das so nicht.

Doch, das geht selbstverständlich auch "mit Visual Studio" so. Auf genau 
diese Art und Weise.

Wenn man es schafft, den C++-Compiler zu verwenden, und nicht auf 
die Glitzer-Vorgaukel-Welt des .Net-Geraffels 'reinzufallen, das eine 
Pseudoprogrammiersprache mit dem irreführenden Namen "C++/CLI" anbietet.

Mit Visual Studio kann man natives C++ verwenden, und das verhält sich 
wie natives C++. "WinForms" aber braucht den .Net-Unterbau, und kann 
daher nicht mit C++ genutzt werden.

Wie oft muss man das hier eigentlich noch wiederkäuen?

von Oliver S. (oliverso)


Lesenswert?

Harald K. schrieb:
> Wie oft muss man das hier eigentlich noch wiederkäuen?

Für jemanden, der in "Visual Studio" programmiert, unendlich oft.

Oliver

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.