Integra C ++ DLL con GUI C # in modo asincrono (problema di progettazione)

1

Questo è più un progetto che una domanda di implementazione. Sono a conoscenza di come integrare una DLL C ++ all'interno di un'app principale C # che funge da interfaccia grafica. Credimi che ho letto tutte le altre domande su argomenti simili, ma nessuno di loro risponde chiaramente alla mia domanda, quindi eccoci qui:

  • Ho una DLL C ++ con alcune funzioni che interagiscono con un'API con un altro sistema (scatola nera per me). La funzione che si collega all'API deve essere "viva" mentre l'intero programma è in esecuzione, altrimenti la connessione all'API viene persa e tutto diventa più difficile. Quindi, tenendo a mente che se chiamo la funzione "Connetti" nella DLL e poi torno al codice C #, il codice DLL sarà fuori dal contesto (non più in esecuzione), e si verificherà la disconnessione (correggimi se io ' m sbagliato per favore).

  • Finora sembra che quello di cui ho bisogno è:

    a) Chiama le funzioni DLL C ++ usando P / Invoke come al solito

    b) Disegna un meccanismo che mantiene la funzione DLL (comprese le chiamate ad altre funzioni all'interno della DLL sempre attive)

    c) Ogni volta che il modulo DLL C ++ ha nuovi dati nuovi, richiama il C # e aggiorna tutti i dati necessari per la presentazione.

Sembra facile, ma non riesco a realizzare il progetto in modo che nessuno di loro resti bloccato. Ho provato ad usare loop infiniti nel lato C ++ DLL, ma poi la GUI si blocca. Se eseguo semplicemente una chiamata alla DLL ogni "x" secondi, quindi sto interrogando troppe volte inutili e la GUI diventa lenta e non elegante nell'aggiornamento. Inoltre, avendo la GUI come "master" e la DLL come "slave", si verifica una disconnessione a causa della DLL che interrompe l'esecuzione mentre si trova nel contesto del codice C #.

Non essere troppo duro con me ragazzi, so che ci deve essere un semplice problema di design che non sto considerando, ma non riesco a scoprire cosa sia. Sono nuovo su C #, non su C ++.

Inoltre, sarei grato se potessi suggerire un'altra soluzione per un caso in cui i dati di aggiornamento dal lato DLL sarebbero quasi in tempo reale, proprio come leggere la velocità istantanea di un veicolo in tempo reale.

    
posta karakol 24.08.2015 - 17:22
fonte

2 risposte

1

a) Call the C++ DLL functions using P/Invoke as usual

Questo indica che l'OP ha non letto tutto quello che c'è.

P / Invoke va bene così com'è, ma per scenari più complessi, un livello C ++ / CLI è molto più appropriato , soprattutto quando si tratta di callback in .NET.

Per il resto della domanda a IMHO non è possibile rispondere senza ulteriori dettagli dall'OP, quindi lascerò perdere.

    
risposta data 16.05.2017 - 11:59
fonte
0

Non è del tutto chiaro cosa stai cercando di realizzare, ma fortunatamente non ha molta importanza, dato che l'aspetto dell'integrazione C # e C ++ non ci gioca proprio per quanto riguarda la gestione delle chiamate di funzione asincrone.

Sia che usi DllImport, (PInvoke), C ++ / CLI o altro, non importa, dato che lo stato degli interi della DLL viene preservato tra le chiamate di funzione.

So, bare in mind that if I call the "Connect" function in the DLL and then I return to C# code, the DLL code will be out of context (no longer under execution), and disconnection will occur (correct me if I'm wrong please).

Questo non è vero. Diamo un'occhiata a un esempio. Crea una semplice DLL:

int foo = 5;

extern "C"
{
    __declspec(dllexport) int GetFoo()
    {
        return foo;
    }

    __declspec(dllexport) void SetFoo(int f)
    {
        foo = f;
    }

    __declspec(dllexport) int GetFooSquared()
    {
        return foo * foo;
    }
}

Quindi creiamo un'app C # che acceda a tali funzioni:

class Program
{
    [DllImport("MyLibrary.dll")]
    static extern int GetFoo();
    [DllImport("MyLibrary.dll")]
    static extern void SetFoo(int b);
    [DllImport("MyLibrary.dll")]
    static extern int GetFooSquared();

    static void Main(string[] args)
    {
        Console.WriteLine("Get foo {0}", GetFoo());

        SetFoo(7);
        Console.WriteLine("Get foo {0}", GetFoo());
        Console.WriteLine("Get foo squared {0}", GetFooSquared());
    }
}

E se lo eseguiamo, la nostra variabile foo nella dll verrà modificata e il valore modificato verrà mantenuto tra le chiamate di funzione. Quando si avvia la libreria C #, quando viene eseguita la prima chiamata a MyLibrary.dll, la libreria viene caricata e il suo spazio di memoria rimane caricato.

Eseguendo l'esempio otteniamo un output previsto che indica che lo stato è preservato:

 Get foo 5
 Get foo 7
 Get foo squared 49

Quindi, struttura il tuo design immaginando come lo faresti se fosse tutto in una lingua, C # o C ++. Qualunque sia il design che si presenta, l'unica modifica necessaria per farlo funzionare è attraversare il confine C # / C ++. Le opzioni per farlo è scrivere una classe C ++ / CLI per mappare le strutture dati avanti e indietro o per collegare tutto ciò che riguarda le chiamate di funzione in stile C, ma quelle non sono molto difficili, e c'è una varietà di modi per farlo funzionare.

Ma alla fine non hai bisogno di nessun ciclo di attesa o qualcosa del genere perché la tua DLL non si "disconnette" senza che tu stia attraversando alcuni seri cerchi per farlo intenzionalmente.

    
risposta data 16.05.2017 - 18:50
fonte

Leggi altre domande sui tag