Conversia unui proiect din C++ în C# (Programare, C#, C++)

Ralph Trickey a intrebat.

Am un proiect la scară medie (un joc pe rând) care în prezent este scris în C/C++. Doar o singură persoană lucrează la el. Va fi compatibil cu /clr, deși nu am încercat /clr:pure.

Caut sfaturi cu privire la procesul general de conversie în C#.

Este vorba în principal de C cu un strat subțire de C++ (C cu clase statice/singletul pentru definire a domeniului de aplicare). Da, nu este un OO „real”, am plănuit să fac mai întâi conversia în C# pentru a evita crearea de probleme de conversie în timpul conversiei.

Folosește foarte puțin STL (Clasa de coadă) în modulul de orientare și, pentru că este un joc, nu face nici o alocare de memorie în afară de biblioteca de sunet terță parte într-o DLL și de ceea ce este necesar pentru încărcarea hărților grafice.

Vreau să îl convertesc în C# idiomatic. Aș prefera să nu țin o discuție dacă e o idee bună, am înțeles că nu este, hai să lăsăm partea asta, vă rog. Să presupunem că am motive imperative, vă rog.

M-am documentat și eu și există un thread oarecum relevant despre conversia metodelor folosind reflector. Intenționez să mă uit mai adânc în ea când voi avea ocazia.

Traducere C++/CLI în C#

Există, de asemenea, o aplicație cu plată care va converti din C++ în C# pe care aș putea să o examinez dacă aceasta nu funcționează atât de bine pe cât mi-aș dori.

Cea mai grea parte va fi rescrierea interfeței fie în WPF/Silverlight, fie în XNA (sau în ambele) Există avantaje și dezavantaje pentru fiecare, dar acum înclin spre WPF din cauza suportului pentru fonturi și pentru că astfel nu va trebui să scriu toate widget-urile. S-ar putea să ajung să le fac pe amândouă, un port rapid XNA și unul WPF mai târziu.

Există mai multe abordări posibile în acest sens și am vrut să știu dacă cineva are experiență cu o astfel de conversie și dacă are sugestii sau capcane.

1) Creați mai întâi interfața de utilizare, Acest lucru implică fie să lăsați modulul grafic așa cum este, și să convertiți din GDI în GDI brut, ca și apelurile în XNA, și să convertiți mai târziu în WPF, câte un dialog pe rând.

2) Convertiți mai întâi intestinele și lăsați deocamdată interfața principală în C++/CLI, iar după ce intestinele sunt convertite, treceți interfața la WPF, dialog după dialog.

O întrebare conexă este dacă merită să faceți acest lucru modul cu modul sau, practic, totul deodată, și dacă este mai bine să faceți o conversie brută în C# și să curățați totul sau să curățați totul în C++ și apoi să faceți conversia în C#.

În acest moment, ideea este să rescriu buclele de evenimente pentru a folosi o buclă comună de tip MFC, apoi să încerc să convertesc totul deodată în C#. Lăsați grafica în C++ și vedeți ce se strică. După aceea, treceți la XNA și oferiți un strat WPF mai târziu. Ultimii doi pași sunt arbitrari, cred că portarea XNA va fi mai simplă, dar folosirea panoului de bază WPF poate fi și ea destul de simplă.

Sunt deschis la orice sugestie care ar putea ajuta.

Mulțumesc, Ralph

Comentarii

  • Am găsit această postare în timp ce mă gândeam să fac același lucru la ceea ce sunt destul de sigur că este exact același joc turn-based pe care îl întrebai acum șapte ani. Presupun că nu a dus nicăieri, totuși. –  > Por Bobson.
  • Am decis să continui în C++. Am scris un framework UI în loc să încerc să schimb totul în C#. Ar trebui să public mai târziu în acest an. –  > Por Ralph Trickey.
  • Aștept cu nerăbdare! –  > Por Bobson.
6 răspunsuri
Andrew Hare

Trebuie să spun că cel mai bun sfat pe care vi-l pot da este să rescrieți aplicația. C++ și C# sunt atât de diferite încât, dacă sunteți sigur că doriți să convertiți totul, atunci o rescriere va fi cel mai probabil cea mai bună opțiune.

Cred că întrebarea mea principală este de ce doriți să convertiți acest proiect în C#? Înțeleg că nu aceasta este întrebarea dvs. dar din moment ce întreprindeți ceea ce eu consider a fi un considerabil efort considerabil pentru a face acest lucru, sper că vă dați seama în ce vă băgați.

Comentarii

  • Da, înțeleg pe deplin volumul de muncă implicat. Mă ocup de C++ de când a fost folosit CFront și de C# ocazional de la 1.0. Speram la un sfat semnificativ, dar mulțumesc oricum. –  > Por Ralph Trickey.
  • Nu vreau să vă dau cu piciorul, dar cred că am că am oferit un sfat semnificativ. Este imposibil pentru oricine să cunoască profunzimea acestui proiect și să te ajute să găsești o modalitate bună de a-l ataca. Căutați să schimbați o aplicație neadministrată în una administrată – acest lucru nu este banal! Dacă am ști de ce doriți să schimbați, am putea fi în măsură să vă ajutăm. Cu alte cuvinte, dacă ați fost încântat să folosiți WPF, atunci v-am putea sfătui să reconstruiți doar interfața de utilizare și să lăsați restul aplicației așa cum este. Fără mai multe informații este foarte dificil să oferim un alt sfat decât „rescrieți totul”. –  > Por Andrew Hare.
  • Ciudat, nu știu de ce nu am fost anunțat că ai postat un comentariu. Motivul principal este că mă aștept să mențin acest program timp de 10+ ani, iar jobul meu de zi este C#. De asemenea, vreau să pot face WPF și, eventual, XNA. Întreaga interfață trebuie înlocuită, iar până atunci curățarea ei astfel încât să pot face C# cu totul este destul de simplă. Speram că cineva a făcut ceva similar și ar putea avea sfaturi despre ce a funcționat pentru ei. (UI mai întâi, totul în C#, apoi UI în WPF, C++ Native în DLL-uri vs Managed C++ mai întâi, etc.) Știu foarte bine cât de multă muncă este. –  > Por Ralph Trickey.
Ralph Trickey

Am aflat că CodeRush (pe care îl dețin deja) are o operațiune de „smart paste” care face o treabă rezonabilă de convertire a ceea ce poate fi conferit. Există, de asemenea, un add-in CR_Paste pe googleplex care face ceva similar. (este posibil ca add-in-ul CR_Paste să nu necesite Coderush, ci doar aplicația gratuită DXCore.

Din moment ce voi avea acces deplin la arborele de analiză (și înțeleg arborele de analiză), pot (și nu pot) să-l personalizez pentru a schimba char * în String, etc. Dacă voi face multe personalizări, probabil că voi crea o versiune open source, probabil pe CodePlex.

Ralph

Comentarii

  • OK, Iată planul meu provizoriu Voi adăuga mai multe mai târziu. 1) schimb toate metodele care seamănă cu unit_agility(the_unit) în units[the_unit].agility(). Acesta ar trebui să fie o mare parte din cod în afara funcțiilor grafice de utilitate. 2) Puneți toate celelalte metode în clase statice, doar pentru a putea compila în C# mai târziu. 3) Împărțiți în clase „Dialog” separate tot codul care atinge interfața de utilizare. O mare parte din acesta se află în aceleași fișiere în acest moment, dar ar trebui să fie ușor de separat. 4) Convertiți toate șirurile de caractere în std::string și analizați posibilitatea de a folosi DXCore pentru a le converti în System::string (sau faceți o căutare/înlocuire globală.) -.  > Por Ralph Trickey.
FenixEden

Cu Visual Studio 2013 Express

Puteți, de fapt, să deschideți două ferestre ale acestuia (să spunem VSEx 2013 (1) și VSEx 2013 (2)).

Îl deschideți mai întâi, deschideți proiectul existent, apoi : faceți clic dreapta pe pictograma sa din bara de activități și faceți clic pe Visual Studio 2013 Express… Acest lucru va deschide a doua oară aplicația, o veți avea executată de două ori în același timp.

Pentru că motivul pentru care am căzut pe postarea ta… lol… este pentru că și eu căutam același lucru.

Ce am făcut în continuare a fost frumos.

Modificare : Selectați AllCopy…

Mergeți pe cealaltă „fereastră” a VS Express 2013,Paste…

Apoi, bineînțeles, s-ar putea să primiți mini erori, cum ar fi culorile care trebuie resetate, formele care trebuie redefinite și toate :: și -> pentru a „modifica înlocuiți : :: cu . și -> cu . (Probabil că va trebui să recreați toate „Evenimentele” totuși, dar în mod normal : toate proprietățile implicite vor fi setate așa cum le-ați stabilit în setările originale.

Apoi, dacă ați primit erori la lipire de genul (object cannot be found), înseamnă că, în mare parte, unul dintre controalele dvs. este de fapt un .COM sau o chestie încorporată… Adăugați-l așa cum ați făcut în versiunile mai vechi ale Visual C++ (exemplu : afișați : caseta de instrumente, apoi faceți clic dreapta în ea și adăugați ITems (sau alegeți elemente) și apoi adăugați-l în mod normal)…

Sper că vă ajută.

(De fapt, îmi refac tot programul VC++ 2010, în C# 2013).

Distracție plăcută 🙂

Comentarii

  • enums, structs și unions vor necesita o atenție deosebită, alături de a afla dacă *foo ar fi un pointer la un singur obiect sau la o matrice… –  > Por Emyr.
Gregor

Sunt ocupat să convertesc codul C++ în cod c#.

Mi se pare mult mai rapid și mai ușor decât am crezut. și da, de asemenea, vreau mai întâi să fie identic înainte de a face modificări în unele cazuri, cum ar fi algoritmii științifici, doriți un rezultat identic, dacă nu există repere de referință.

Ei bine, din moment ce codul dvs. este mai mult bazat pe c, acest lucru vă va da doar cod c# spagetti pe care trebuie să-l refactorizați mai târziu în clase. Presupun că veți avea inițial o mulțime de metode statice care erau funcțiile dvs. în c. Încercați să grupați unele date și metode împreună în cazul în care acestea descriu comportamentul obiectelor.

Eu o fac este fișier cu fișier, linie cu linie. începând cu măruntaiele. când găsesc ceva complet depășit, îl înlocuiesc cu echivalentul c#, folosind Lists , IEnumerables etc. Unele dintre calculele de nivel scăzut pot fi înlocuite cu biblioteci standard C#.

V-aș sfătui să nu folosiți unsafe C#. Există adesea o modalitate mai ușoară și mai economică de a ocoli acest lucru. Calculele de pointer pot fi păstrate foarte asemănătoare cu codul C++ și sunt unele dintre cele mai rapide lucruri care se traduc.

De ex.

double* array_p;

se convertește în

double[] array_p

acum, atâta timp cât ați făcut referire la array_p[i] după aceea, unde i este un int, codul rămâne același dacă ați făcut incrementări ale pointerilor array_p ++, folosiți un int, care începe de la 0 și crește.de exemplu, i++. și apelați

array_p[i]

Trecerea pointerilor la pointeri de la o metodă la alta, de exemplu *array_p înseamnă doar trecerea unei referințe la array_p în c#. În esență, în c#, toate clasele sunt transmise prin referință în orice caz, astfel încât nu este nevoie de atâția pointeri.

Cu toate acestea, aș scrie ghidul de la zero. OO și non-OO sunt prea diferite pentru asta.

Mult noroc. Testați codul de nivel scăzut și curățați-l acolo unde este posibil.

alexD

Se pare că aveți nevoie de o reproiectare a aplicației, nu doar de o conversie de cod. Conversia unei aplicații non-OO C/C++ în C# nu pare a fi un obiectiv realist.

Daniela Moya
#include <iostream>
using namespace std;

int main(int argc, char *argv[]) {
    char a;//letra
    int num;//cantidad a imprimir

    //Ingresa los datos
    cout<<"Introduce la letra "<<endl;
    cin>>a;
    cout<<"Introduce la cantidad para imprimir "<<endl;
    cin>>num;

    //imprime de 5 a 1
    for(int i=num; i>0; i--)
    {
        for(int c=0; c<i; c++)
            cout<<a;
        cout<<endl;
    }

    //imprime de 1 a 5
    for(int i=0; i<num; i++)
    {
        for(int c=0; c<=i; c++)
            cout<<a;
        cout<<endl;
    }
    return 0;
}

Tags: