Hallo Zusammen, hier ist bestimmt jemand der mir helfen kann. Ich entschuldige mich gleich mal, da die kenntnisse von mir mit C++ und PC-Programmierung nicht so toll ist. Aber vielleicht bekomme ich es mit hilfe trotzdem hin. Ich versuche mal mein Problem so gut wie möglich zu erklären. Prinzipell geht es um eine Verbindung zwischen ein PC-Programm und dem Microsoft Flugsimulator X. Es gibt die Software FSUIPC mit der man direkt in den Simulator kommt. Ich habe nun versucht auf diese Software zuzugreifen. Es gibt noch eine API mit fertigem Code den man direkt einbinden kann. Also habe ich mir Visual Studio 2015 besorgt und das mal Probiert. In einem Allgemeinen Projekt hat das auch funktioniert. Nun wollte ich das ganze aber gern mit einer Benutzeroberfläche haben. Also ein leeres CLR Projekt erstellt. Da ein kleines Tutorial gemacht um die Funktion ein bisschen kenner zu lernen. (Hab ich schon erwähnt, ist mein erstes mal mit Visual Studio 2015, bzw. generell Visual Studio). Dann habe ich das Programm und da den Code aus dem Allgemeinen Projekt erweitert. Nun der Versuch zu Kompilieren hat nicht mehr funktioniert. Nun kommt die Fehlermeldung D8045 Die Datei "IPCuser.c" kann nicht mit der /clr-Option kompiliert werden. Hmm... doof. Nun ein bisschen gegoogelt und mal die Kompilieroptionen probiert. Wenn ich nun die IPCuser.c als C++ Code mit der Option /TP Kompiliere ist der erste Fehler weg dafür eine menge neue ander da. Prinzipell schein es immer der gleich zu sein: Fehler C2664 "int wsprintfW(LPWSTR,LPCWSTR,...)" : Konvertierung von Argument 1 von "char [260]" in "LPWSTR" nicht möglich Und hier komme ich jetzt nicht mehr weiter. Wenn sich jemand erbarmen würde und sich das mal anschauen könnte wäre das echt Spitze und ich könnte vielleicht bis zum nächsten Problem weitermachen. Ich habe das Programm mal mit angehängt wenn jemand reinschauen mag. (Nicht wundern, der Name ist noch von dem ersten Tesprogramm) Vielen Dank für eure Hilfe Schöner Gruß Tobias
In den Projekteigenschaften unter Configuration Properties / General von Unicode auf Multibyte umstellen. Wenn es daran liegen sollte... Andere Frage: Warum muss das unbedingt CLR sein?
Hallo die Umstellung auf Multibyte hat jetzt wieder andere Fehler gebracht. Schaut dann ungefähr so aus: S Fehler LNK2019 Verweis auf nicht aufgel÷stes externes Symbol ""extern "C" unsigned int __stdcall RegisterWindowMessageA(char const *)" (?RegisterWindowMessageA@@$$J14YGIPBD@Z)" in Funktion ""extern "C" int __cdecl FSUIPC_Open(unsigned long,unsigned long *)" (?FSUIPC_Open@@$$J0YAHKPAK@Z)". Was hab ich für alternativen zu CLR? (Was bedeutet das CLR?) Ich bin für alles offen..
Du nutzt, lax gesagt, die Microsoft Variante von Java. Du benutzt die Sprache C++/CLR und nicht C++. Das sind generell zwei unterschiedliche Sprachen! "Javascript to Java is like Ham to Hamster!" Deine "IPCuser.c" ist aber ein C Projekt (wgegen Dateiendung). Deswegen musst du am besten ein C Projekt anlegen. Unter "Neues Projekt" musst du bei Vorlagen Visual C++, Win32, Win32 Konsolenanwendung wählen. Und danach musst du die Hauptdatei die Dateiendung .c verpassen, damit dein Projekt ein C Projekt wird.
mhh ok.. jetzt stellt sich mir nur die Frage wie bekomme ich dann Buttons und Fenster da rein. Mit der CLR Variante ging das ja recht simpel. Sry, aber das alles ist irgendwie so verwirrend und es gibt so viele verschieden möglichkeiten. Da fehlt mir absolut der Überblick.
Ich würde nicht völlig ausschließen, dass es mit den richtigen Einstellungen funktionieren könnte, denn C++/CLI kann mit nativem und managed Code umgehen (darum lassen sich damit ja Wrapper schreiben - was auch so ziemlich die einzige sinnvolle Anwendung von C++/CLI ist). Aber hier würde ich doch eher "normales" C oder C++ und eine entsprechende GUI-Bibliothek empfehlen. Tobias B. schrieb: > jetzt stellt sich mir nur die Frage wie bekomme ich dann Buttons und > Fenster da rein. MFC, WTL, Win32++, wxWidgets, Qt, ...
Wenn es C++ sein soll, dann musst Du eine WIN32 Anwendung erstellen, wie ja bereits jemand sagte. Es muss aber keine Konsole sein, sondern ein WIN32-Projekt. Dann kannst Du mit der guten alten WIN32 API auch Deine Fenster und Buttons einbauen. Nur mal als Beispiel, wie man das so machen kann: http://ahidlib.com/index.php/free-download Wähle die C++ Demo / WIN32 API Anwendung aus. Diese ist zwar für VS2010, sollte aber 'per Knopfdruck' konvertierbar sein. Gruß Klaus
Ich frage mich ja, lieber @OP, im Ernst, wieso du (oder warst du das gar nicht) uns einen Anhang namens "RandomNumberGenerator" geschickt hast. Ist hier was wohl nicht virensicher? Ough! Ansonsten ist dein Post so ein Konglomerat von "ich habe echt wenig Ahnung, aber morgen muss das gehen!" und Freistoßvorlagen für sehr viele "wieso willst du überhaupt was von Microsoft, du musst total kaputt und dumm sein, wir wissen das doch alle besser"-Antworter. Mein Tipp wäre: Lies die Doku zu dem FSUIPC Dings. Wenn dir das ned hilft, schreib den Entwickler an. In der Regel sind Microsoft-Entwickler recht entspannte Menschen mit einem großen Willen zum Teilen. Lass es zwei Tage länger dauern, bis es "Klick!" bei dir macht, so what? (Und ja, ich schreibe hier mit größter Absicht keine angeblichen Hinweise der Art "Lade dir mal das und das herunter, das könnte helfen, aber eigentlich weiß ich es auch nicht" hin ;) ) LG Carsten
So nach viel lesen und probieren und auch nicht verstehen bin ich eigentlich der Meinung das der einfachste weg wäre wenn ich das bestehende Programm welches der FSUIPC bereitstellt zu nehmen und in das CLR Projekt einbinden würde. Vielleicht gibt es ja jemand der mir verständlich zeigen kann wie man sowas macht. Mein Kenntnisse reichen so auf jeden fall nicht aus und ich möchte und kann nicht Wochenlang dafür weiter investieren. Wenn sich jemand findet freut mich das natürlich und wenn nicht das schau ich mal weiter ob es noch wo anderst jemand gibt oder lasse es einfach sein. Danke
Also, Tobias, hier wurde (sorry, wenn das von den Autoren nicht so geplant war) mal wieder viel Microsoft- und CLR-Bashing betrieben in den Antworten. Wichtig zwischen all den anderen Aussagen war der Hinweis darauf, dass C++/CLR nicht dasselbe ist wie C++. Die CLR ("common language runtime") ist eine Sammlung von Bibliotheken im Rahmen dessen, was man in Microsoft-Kreisen "managed code" nennt. Egal, welche Programmiersprache du aus der "managed" Familie nutzt (es gibt u.a. VisualBasic.NET, C#, C++/CLR, F#, Perl und, ich glaube, sogar Python...), der jeweilige Compiler baut daraus (mehr oder weniger) denselben "intermediate language" (IL) Code, der erst bei der Ausführung "just in time" (JIT) wirklich in Maschinencode übersetzt wird. Deswegen ist es z.B. möglich, eine Klassenbibliothek auf einem Windows-PC zu entwickeln mit all den Nettigkeiten, die Visual Studio, Team Foundation Server und die 100.000 Add-ons dazu bieten bis hin zu Scrumban-basiertem Projektmanagement und Integration in MS Project und automatisierten Test- und Deployment-Factories und und und (ja, das gibt es alles auch für andere Umgebungen...), das ganze einfach per Dateikopie auf einen Raspberry zu schubsen und laufen zu lassen. Nix Neukompilieren, läuft einfach. So in etwa funzt das ganze ja auch mit Java. Jedenfalls: es gibt ein paar Stoplerfallen bei der Sache. Zuerst: Alles, was nicht "managed", also CLR ist, musst du einpacken, sprich: Wrapper dazu schreiben. Wenn du einen POCT ("Plain Old C Type") einpackst, ist das easy, weil es keine Abhängigkeiten gibt. Fowler hatte schon Recht. Es gibt das Attribut "DllImportAttribute" in der .NET-Welt. Einfach mal im Studio danach suchen oder bei msdn.microsoft.com (dein bester Freund in der .NET-Welt). Da findest du auch Beispiele, wie du den Wrapper aufbauen musst. Dann: Pfade. .NET ist ziemlich autistisch, was Pfade angeht. Wenn du dich nicht stur an die (sich von Version zu Version gerne mal ändernden) Vorgaben der jeweiligen Windows-Version hältst, findet die Laufzeit keine Bibliotheken, außer mit ganz viel Hexerei in der Registry, und auf anderen Betriebssystemen mit der Mono-Umgebung (eine freie, von Microsoft durchaus gepushte Implementierung für Linux, OSX, Android und Co.) wird es bloß noch schlimmer. Wenn es nämlich keine POxTs sind, sondern die Bibliotheken wiederum Abhängigkeiten mit sich rum schleppen (was die meisten Bibliotheken tun), bist du schnell in der berüchtigten "DLL Hell" und bei "Plug & Pray". Daher: Mache dich mit den Eigenschaften-Seiten von Projekten und Solutions im Visual Studio vertraut. Es gibt dort (sorry, ich hab ne englische Umgebung) sogenannte "Build Events". Dich interessieren an dieser Stelle die "Post-build Events". Dort kannst du z.B. Dateien hin und her kopieren. Das jetzt in aller Ausführlichkeit zu beschreiben, würde ewig dauern -- und ist auch unnötig, weil wie immer msdn.microsoft.net ;) Wenn du schon in den Eigenschaften deiner Projekte rumstocherst, dann sieh zu, dass du alle (!!) Bibliotheken, die du für deine Testläufe brauchst, in den Post-build Events in das Verzeichnis deiner Exe kopierst. Für ein späteres Deployment kannst du das dem Build-Server oder deinem Installer deiner Wahl (MSI, WinRAR, apt, make, ...) aufbürden. So, jetzt nochmal zu den Wrappern. Auch da gehört ein bisschen Lesen dazu, wie man Prozeduren, Funktionen, Methoden, Eigenschaften aus Bibliotheken welcher Herkunft einpackt. Grundsätzlich ist aus dem Blickwinkel der Software-Architektur die beste Vorgehensweise 3-stufig: Der erste Wrapper ist eine eigenständige Bibliothek, die 1:1 alle angebotenen Sachen (Prozeduren, Funktionen, Methoden, Eigenschaften, Konstanten...) in die CLR überführt (und in eine Klasse schiebt). Welche Sprache aus der Familie der, die es für .NET gibt, nimmst, ist deine Entscheidung. Als jemand, der ursprünglich aus der C-Ecke kommt, gibt es für mich nur C# und je nach Fall auch F#. Falls du mehr der Python-Mensch bist, fühlst du dich bei VisualBasic.NET vielleicht wohler. Aber wie gesagt, soweit ich weiß, gibt es auch eine Python.NET-Version. Hat mich halt nie interessiert. Es steht eben nicht jeder auf Rothaarige ;) Jedenfalls übersetzt du alles 1:1 von der ursprünglichen Bibliothek in etwas CLR-Konformes. Wie gesagt, suche im MSDN nach dem "DllImportAttribute", da gibt es mehr. Ein weiteres wichtiges Thema ist das "Marshalling". Einfach Google oder MSDN danach fragen und lesen. Der zweite Wrapper ist ebenfalls eine eigenständige Bibliothek, in der du das Interface der ursprünglichen Bibliothek entgültig CLR-konferm machst. Ein Beispiel ist dein Problem "char[260] zu LPWSTR". In der CLR ist das einfach ein String (plus ein bisschen Konfiguration), und die CLR stellt die passenden Werkzeuge bereit, um das hin und her zu schubsen. "char[260]" ist eigentlich ein 260 Einträge großes Feld aus vorzeichenlosen 8-Bit-Werten, während ein LPWSTR ein "Lang-Zeiger" auf eine "wort-basierte Zeichenkette" ist. Eine "wort-basierte Zeichenkette" wiederum ist eine UTF16-Zeichenkette, wobei jedes Zeichen durch einen 16-Bit-Wert dargestellt wird. Wie gesagt, die .NET-Laufzeit bietet für den ganzen Kram passende (und einfache) Werkzeuge an, die dir die Bit-Fummelei abnehmen. Dein Ziel in diesem Wrapper sollte sein, alle Parameter und Rückgabewerte so hinzubiegen, dass sie dem Typen-System der .NET-Laufzeit entsprechen. Weiterhin solltest du die Signaturen der Methoden (C#-Duktus) so verändern, dass es keine "ref" und "out"-Parameter mehr gibt. Auch wenn die .NET-Laufzeit selbst solche hässlichen Entlein enthält, ist es guter Stil (in Sachen Lesbarkeit, Wartbarkeit, Entkopplung), sich ihrer so weit es geht zu entledigen (google mal nach "Open Close Principle"). Wann immer du in den Parametern einer Signatur einer C++-Methode etwas wie "*CMyClass" siehst, wird es ganz schrecklich, und du musst da mal ran! Wenn eine Methode mehr als einen einfachen Rückgabewert liefern will, schreibe eine neue Klasse und packe die Ergebnisse da rein. Der dritte Wrapper gehört bereits zu deiner Anwendung, ist aber trotzdem eine eigene Bibliothek. Hier zimmerst du dir die eigentliche Bibliothek so zurecht, wie deine Anwendung sie benötigt. Bis zum zweiten Wrapper ist es okay, wenn du bei neuen Versionen der eigentlichen DLL nachfummeln musst. Der dritte Wrapper sollte (außer bei ganz großen Änderungen natürlich) davon nicht betroffen sein. Die größere Abhängigkeit besteht zu deiner Anwendung. Du musst also dafür sorgen, dass dieser Wrapper vom zweiten so weit wie möglich entkoppelt ist. Dazu kannst du z.B. Interfaces oder abstrakte Klassen benutzen oder am besten gleich einen sogenannten "Inversion of Control container". Zum Lesen, starte mal bei "https://en.wikipedia.org/wiki/Castle_Project#Features" und folge den Links dort. Zusammenfassend: - Der erste Wrapper packt die eigentliche Bibliothek ein und kümmert sich um das Hin und Her zwischen "managed" und "unmanaged" Code. Dazu gehört noch mehr, etwa die Ausnahmen-Behandlung, aber jetzt muss auch mal gut sein. - Der zweite Wrapper packt den ersten ein und kümmert sich vor allem darum, dass das "unmanaged" komplett verschwindet. Dazu gehört wieder ein bisschen mehr, etwa dass du sicherstellst, dass der Code in der Domäne eines normalen Anwenders lauffähig ist. - Der dritte Wrapper packt den zweiten ein und ist quasi eine "Facade" (googlen!) für deine Anwendung. Dort biegst du dir die eigentliche Bibliothek so zurecht, wie du sie brauchst, aber eben auf der Basis des zweiten, managed Wrappers. - Im VS in den Build Events kopierst du dir alles so hin und her, dass das, was du brauchst, im selben Verzeichnis endet. Mal ein Beispiel zur Veranschaulichung: Du hast einen speziellen Spiele-Controller, der mit einem Treiber geliefert wird, der sich zum Glück einigermaßen offenbart. Der Treiber wurde in C geschrieben und schiebt zig Konstanten und Funktionen hin und her, samt "Hooks", also hässlichen Funktionszeigern, die was tun, wenn ein Knopf auf dem Controller gedrückt wird. Im ersten Wrapper übersetzt du dann bloß 1:1 alles, was der Treiber liefert, in managed Code mit dem .NET-Typensystem. Im zweiten Wrapper kümmerst du dich darum, dass die Signaturen CLR-kompatibel werden und darum, dass du den ersten Wrapper ohne besondere Benutzer-Rechte aufrufen kannst. Hier kannst du auch Timing-Probleme und einfache Werte-Umwandlungen (im Treiber: "fire_button_pressed = false", in deinem Wrapper: "FireButtonPressed = !(fire_button_pressed)" (damit "true" rauskommt, wenn der Knopf gedrückt wird), oder du machst aus dem Drückeberger-Ding ein Ereignis und definierst dafür einen Event) vornehmen. Im dritten Wrapper reichst du entweder den Wert von "FireButtonPressed" durch oder schreibst einen Ereignis-Behandler und verbindest ihn mit dem definierten Ereignis, sodass du noch weiter in den empfohlenen Mustern in der CLR-Welt bist. Wieso das sinnvoll ist? Nehmen wir an, das Drücken von zwei Knöpfen gleichzeitig hat eine spezielle Bedeutung für dein Spiel, aber der Treiber liefert nur die einzelnen Knöpfchendrück-Werte. Dann kannst du in diesem dritten, deiner Anwendung angepassten Wrapper daraus einen neuen Event "KillThemAllEvent" erstellen. Es ist dann also nicht mehr nötig, dass du in deiner Anwendung durch alle Schichten tauchst und abfragst, ob beide Knöpfe innerhalb einer gewissen Verzögerungszeit gedrückt wurden. Du hängst dich einfach an den Event im Wrapper, und wenn dieses Ereignis passiert, wird dein Code in der Anwendung von ganz alleine aufgerufen. So, und was ist jetzt "eine gewisse Verzögerungszeit"? Legst du die selbst fest? Nein, tust du natürlich nicht. Das überlässt du der Konfiguration. Für eSports Bundesliga-Daddler mögen für einen Move 50 ms passend sein, fürs Altersheim zur Mobilisierung der älteren Herrschaften eher 1 s. Dafür gibt es "System.Configuration". Auch da mal lesen ;) LG Carsten
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.