Komunikacja między aplikacjami w MinGW i c#

0

Witam!

Staram sie napisac program, ktory bedzie sie komunikowal z drugm. Jeden bedzie napisany w c++ a drugi w c#.
Staram sie zbudowac Hardware in loop, wiec korzystam z openModelica. Ten symulator pozwala na implementacje funkcji c/c++ w swoim kodzie. Z tego co wiem kozysta on z MinGW (lub gcc , nie znam sie na tym za bardzo) do kompilacji programu/symulacji. Natomiast bede chcial polaczyc symulacje z wizualizacja w c# (XNA Game Studio).

Pytanie jak to najlatwiej zrobic? Co polecacie? I jak to wykonac.

0

a jak z predkoscia dzialania takiego rozwiazania? zmieszcze sie z 10 transmisjami (po 32 bity) na sekunde?

1

Tak. Aczkolwiek są również inne możliwości rozwiązania tego problemu. Czy twoja aplikacja symulacyjna może działać jako biblioteka? Czy może eksportować funkcje C? Wtedy wystarczyłoby użyć DllImport po stronie C#.

0

Symulacja to kod w C, ktory ma w sobie zintegrowany solver. Wykonujac jedna petle oblicza stan modelu i wyniki zapisuje do pliku. Jak symulacja/program w c sie wykona to dostaje gotowy plik z wynikiem. Wiec skoro da sie z tego zrobic exe to i pewnie da sie zrobic dll. Tylko tutaj jest haczyk, solver(rownan rozniczkowych) oblicza nastepne kroki na podstawie poprzednich wiec za kazdym razem kiedy dll byla by wywolywana to musiala by znac warunki poczatkowe (poprzednie) do rownanan dla solvera. Pewnie mogla by je odczytac z pliku ale to wolne i obawiam sie ze za glebokie/trudne dla mnie.

0

Jednak wybieram TCP, zobaczymy jak pojdzie. Zaczynam pisac ale bede mial jeszcze pare pytan wiec prosze o nie zamykanie tematu :).

0

@_13th_Dragon: za tą genialną sugestię z TCP powinieneś na IBSPAN zostać zdegradowanym do woźnego. I to nie pierwszy żałosny post...

Serio, to tak genialne jak pisanie notatek poprzez przyczepienie sobie wiecznego pióra do wacka i machanie nim :|

1

Ok. Bardzo mnie cieszy, ze zaczynacie sie przepychc w tym watku ale jakos nic mi to nie pomaga ani niczego nie wnosi, to zwykle TROLOWANIE.
Czy moze da sie zrobic komunikacje za pomoca sendmessage?
Albo skoro juz zaczelem czytac o socket - jak stawiac serwer i klijenta, to moze ktos mi poda jakies dobre materialy do tego jak to zrealizowac w gcc(minGW). I czy mozna do tego wykozystac np. System.IO.Pipes.
A moze da sie zrobic aby oba programy jakos wspoldzielily jakies komorki pamieci :) to by bylo najszybsze wyjscie.

0

A moze da sie zrobic aby oba programy jakos wspoldzielily jakies komorki pamieci :) to by bylo najszybsze wyjscie.

No właśnie jeśli wepniesz jeden program do drugiego jako moduł DLL to będą współdzieliły pamięć. I to jest najlepsze wyjście, a wcale nie trudne w implementacji - z TCP byłoby nawet więcej zabawy.

0

Z tego co wiem to jak sie robi dllimport to dll-ka jest odpalana jak exe - wykonuje funkcje, ktora ma wykonac a potem sie wylacza. W tym czasie program, ktory ja wywolal czeka na zakonczenie (wkonanie funkcji i zwrot wartosci). I tak w kolko. Jak juz wczesniej napisalem jezeli zrobic dll z symulacji w c to nie bedzie miec warunkow poczatkowych a pisanie funkcji, ktora je bedzie ustawiac nie jest takie latwe nie znajac kodu, poza tym skads trzeba je kazdorazowo wczytac. Jezeli zrobie dll z wizualizacji w c# to dopiero bedzie sajgon jak kazdorazowo bedzie musialo otwierac nowe okno dx9.

0

Że co? DLLka jest podpinana do programu, może wyeksportować jakieś funkcje, których potem będzie mógł używać program. Normalnie będzie podpięta przez cały czas działania programu + podczas zdarzeń typu wpięcie lub wypięcie DLLki odpali się odpowiedni callback umożliwiający wykonanie dodatkowych czynności. Czego nie rozumiesz?

0

W tym czasie program, ktory ja wywolal czeka na zakonczenie (wkonanie funkcji i zwrot wartosci). I tak w kolko.

Funkcja z DLL-ki staje się funkcją w programie (nie osobnym programem), więc o ile nie używasz wielowątkowości, to tak, program oczywiście czeka, tak jak się to dzieje z każdą inną funkcją.
Ale DLL-ka nie jest za każdym wywołaniem ładowana na nowo, więc jak najbardziej może przechowywać swój stan pomiędzy wywołaniami.

Co do kwestii która część ma być w DLL a która w EXE:
Znacznie łatwiej jest spod C# załadować dllkę napisaną w C albo C++, niż z C załadować dllkę napisaną w C#.

W pierwszym przypadku używa się po prostu DllImport.
W drugim trzeba albo napisać pomost w C++/CLI, który ma dostęp z obu stron, albo bawić się w CLR Hosting (czego nie robiłem, bo przykłady mnie odstraszają), albo bawić się w interfejsy COM (czego też nie robiłem, bo nie było po co).
Z tych trzech rozwiązań jakby to ode mnie zależało, pewnie bym wybrał czwarte, czyli zamiast w C# i C napisać całość w C++/CLI.

0

Ok, rozumiem ze dll bylo by najlepszym i najszybszym wyjsciem. Jednak symulacji, ktora ma z 12 include-ow na dllke to raczej nie bedzie latwe. Nawet nie wiem co tam w srodku siedzi a co dopiero przerabiac to na dll. Jednak zrobienie servera na socket-cie wydaje sie znacznie lepszym rozwiazaniem.

0

My tu gady gadu a ja znalazlem dzialajacy kod komunikacji po socket :
Fajnie by bylo gdyby, ktos mi powiedzial czy sie nada i jakie sa minusy takiego rozwiazania, najbardziej chodzi o obciazenie procesora i stabilnosc w czasie bo o ile wiem tcp nie pozwala na bezzwloczne przeslanie danych (zawsze kolejkuje).

#ifdef WIN32
#include <Winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>

    #define closesocket close
 #endif

#include <stdio.h>

#define D_PORT      4344
#define D_HOST      "localhost"
#define D_QUEUE     32
#define D_SOCKETS   16
#define D_INFO      256
 
int main(int argc, char **argv) {
    struct timeval tv;
    struct sockaddr_in addr;
    struct hostent *host;
    unsigned int descriptor;
    int result;
    int index;
    int cycle = 0;
    int delay = 0;
    unsigned int sockets[D_SOCKETS];
    int sockets_index = 0;
unsigned int maximun;
    char buffer[D_INFO];
fd_set input;
 
    /*  read the delay if any  */
    if (argc > 1)
        delay = atol(argv[1]);
    else
        delay = 0;
 
#ifdef WIN32
WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

#endif /* WIN32 */

    /*  create a socket  */
    descriptor = socket(PF_INET, SOCK_STREAM, 0);
    if (descriptor == -1) {
        perror("socket");
        return (1);
    }
 
/*  get information about the host  */
    memset(&addr, 0, sizeof(addr));
    host = gethostbyname(D_HOST);
if (host == NULL) {
        perror("gethostbyname");
        closesocket(descriptor);
#ifdef WIN32
        WSACleanup();
#endif
        return (1);
    }

    /*  bind the socket to an address and port  */
memcpy(&addr.sin_addr, host->h_addr_list[0], sizeof(host->h_addr_list[0]));
    addr.sin_family = AF_INET;

addr.sin_port = htons(D_PORT);
result = bind(descriptor, (struct sockaddr *)&addr, sizeof(addr));
if (result == -1) {
perror("bind");
closesocket(descriptor);
#ifdef WIN32
WSACleanup();
#endif
return (1);
}

    /*  listen for connections  */
    result = listen(descriptor, D_QUEUE);
    if (result == -1) {
        perror("listen");
        closesocket(descriptor);
#ifdef WIN32
        WSACleanup();
#endif
        return (1);
    }
 
    memset(sockets, 0, sizeof(sockets));
    maximun = descriptor;
 
    result = 0;
while (result != -1) {
   FD_ZERO(&input);
    FD_SET(descriptor, &input);
        for (result = 0; result < sockets_index; result++)
            FD_SET(sockets[result], &input);
 
        tv.tv_sec  = delay;
        tv.tv_usec = 0;
        if (delay == -1)
       result = select(maximun + 1, &input, NULL, NULL, NULL);
        else
            result = select(maximun + 1, &input, NULL, NULL, &tv);
        switch (result) {
        /*  error in select  */
        case -1:
                perror("select");
           break;
 
            /*  nothing to process  */
            case 0:
                break;
 
            /*  a number of sockets are ready for reading  */
            default:
                /*  check if the descriptor set is our listening one  */
                if (FD_ISSET(descriptor , &input)) {
                    sockets[sockets_index] = accept(descriptor, NULL, NULL);
                    if (sockets[sockets_index] == -1) {
                        perror("accept");
                    }
                    else {
                        if (sockets[sockets_index] > maximun)
                       maximun = sockets[sockets_index];
 
                        sockets_index++;
                    }
            }
                /*  one of the sockets is sending data. Find it  */
            else {
                for (index = 0; index < sockets_index; index++) {
                        if (FD_ISSET(sockets[index], &input)) {
                       memset(buffer, 0, sizeof(buffer));

                            /*  read information from socket  */
                        result = recv(sockets[index], buffer, sizeof(buffer), 0);
                            if (result == -1)
                            perror("recv");
                            else
                                printf("Received %d bytes from descriptor %d: %s\n", result, sockets[index], buffer);
                    }
                    }
                }
        }
 
    printf("%d\r", cycle++);
    }
 
    for (result = 0; result < sockets_index; result++) {
        closesocket(sockets[sockets_index]);
    }

    closesocket(descriptor);
 #ifdef WIN32
    WSACleanup();
#endif
 
    return (0);
}
1

Jest multum możliwości komunikacji między C an C#.
TCP/IP jest chyba najwolniejszym sposobem. Ale przy 10 zdarzeniach na sekundę to pewnie i na kartce papieru byś zdążył to przesyłać. To bardzo niskie wymagania, chyba że 10 razy na sek masz wysłać 1 GB danych.

Najprościej użyć DLL-ki (napisanej w C, wywołanej z C#).
Inne sposoby są możliwe (ostatecznie nawet TCPIP) ale to wyważanie otwartych drzwi.

Zobacz:
http://msdn.microsoft.com/en-us/library/aa365574%28VS.85%29.aspx

0

Ok. Wiec jest mozliwosc zrobienia dll z symulacji (youpiii). Niestety ta opcja nie byla rozwijana od 2010 roku, co nie znaczy ze nie dziala.
Wiec oprocz dll jest generowany plik lib, czy w nim sa przechowywane definicje funkcji i czy jest potrzebny?

1

Dla C# nie jest .lib potrzebny, wystarczy .dll

czy w nim sa przechowywane definicje funkcji
Nie, tylko deklaracje dla linkera.

0

Dobra zobacze czy uda sie to zrobic :) Dam znac czy mi sie udalo.
Dzienx za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1