Kommunikation zwischen C++ und C#



  • Hallo User!

    Ich versuche mal das Problem zu erläutern. Ich arbeite mit Visual Studio 2010.

    Folgendes:

    Ich habe eine dll, die in Visual Basic (2008) geschrieben ist. Diese dll führt Berechnungen durch. Ich wollte diese dll mit Hilfe von c++ ansprechen. Ich habe mir überlegt, dass ich eine Named Pipe erzeuge, um damit eine Kommunikation aufbauen zu können. Das habe ich auch gemacht. Es funktioniert auch. Ich habe eine Berechnung durchgeführt und das Ergebnis über die Named Pipe geschickt. C++ hat die Daten auch erhalten können, aber jetzt kommt das Problem. Wenn ich einen Paramter ändere(Die Größe der zu sendenen Bytes), dann zeigt mir C++ bei der Ausgabe nur mehrere i an. Hier mal der Code

    Der C# Server

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.IO;
    using System.IO.Pipes;
    using System.Web;
    namespace CServerPipe
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Thermodynamic
                string s2 = "";
    
                string s = "2<1<3<7<0<1\0";
                //s2 = "2<0<3<7<0<1\0";
                //Console.WriteLine(s2);
    
                ServerPipe myNewPipe = new ServerPipe("my_pipe");
                myNewPipe.SetContent(s);
    
                ParameterizedThreadStart pts = new ParameterizedThreadStart(myNewPipe.methode);
    
                Thread thread = new Thread(pts);
    
                Console.WriteLine("Helloworld");
    
                thread.Start(s);
    
                myNewPipe.SetActivate();
    
                //myNewPipe.Stop();
    
                myNewPipe.SetContent(s);
    
                //myNewPipe.Stop();
    
                Console.WriteLine("STOP");
            }
        }
    
        // Klassendefinition
        class ServerPipe
        {
            private NamedPipeServerStream pipeServer;
            StreamWriter sw;
            private string mystring;
            private ASCIIEncoding streamEncoding;
            private string mycontent;
            private bool activate, create, WriteOn;
    
            public ServerPipe(string test)
            {
                this.mystring = test;
                activate = true;
                WriteOn = false;
                create = true;
                streamEncoding = new ASCIIEncoding();
    
            }
            ~ServerPipe()
            {
    
            }
            public void SetContent(string newcontent)
            {
                this.mycontent = newcontent;
            }
            public void SetActivate()
            {
                WriteOn = true;
    
            }
            public void Stop()
            {
                WriteOn = false;
            }
    
            public void methode(object myobject)
            {
                using (pipeServer = new NamedPipeServerStream(mystring, PipeDirection.Out))
                {
                    Console.WriteLine("NamedPipeCreated");
                    pipeServer.WaitForConnection();
                    Console.WriteLine("Client connected");
                    try
                    {
                        using (StreamWriter sw = new StreamWriter(pipeServer))
                        {
                            sw.AutoFlush = true;
                            string st = mycontent;
                            string s2 = "2<1<3<7<0<1\0";
    
                            byte[] output = streamEncoding.GetBytes(s2);
                            sw.Write(s2);
                            s2 = "2<0<3<7<0<1\0";
                            output = streamEncoding.GetBytes(s2);
                            sw.Write(s2);
                            s2 = "2<1<3<4<0<1\0";
                            output = streamEncoding.GetBytes(s2);
                            sw.Write(s2);
                            s2 = "2<0<3<4<0<1\0";
                            output = streamEncoding.GetBytes(s2);
                            sw.Write(s2);
                        }
                    }
                    catch (IOException e)
                    {
                        Console.WriteLine("ERROR: {0}", e.Message);
                    }
    
                }
    
            }
        }
        }
    

    //////////////////////////////////////////////////////////

    Ich denke mal, dass der Fehler im c++ Code ist

    const char *temp,*temp2;
    char mybuffer[128]; ------> Das habe ich geändert
    HANDLE pipe;
    bool pipeexist;
    wchar_t buffer[128];-------> Das habe ich geändert
    DWORD numBytesRead;
    BOOL result;

    ------------------------------------------Konstruktor

    temp = "Failed to connect to pipe";
    temp2 = "Reading data from pipe...";
    numBytesRead = 0;

    pipe = CreateFile(
    "\\\.\\pipe\\my_pipe",
    GENERIC_READ, // only need read access
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
    );
    if (pipe == INVALID_HANDLE_VALUE) {
    //"Failed to connect to pipe."
    pipeexist=false;

    }
    else{
    pipeexist=true;
    //"Reading data from pipe..."
    }
    //////////////////////////////////////////////
    Das rufe ich ständig auf

    if (CheckRenderCount()) {
    //------------PIPE
    result = ReadFile(
    pipe,
    buffer, // the data from the pipe will be put here
    127 * sizeof(wchar_t), // number of bytes allocated
    &numBytesRead, // this will store number of bytes actually read
    NULL // not using overlapped IO
    );
    //----------------------------
    stringchannel = (Aco_StringChannel*)GetChild(0);
    stringchannel2 = (Aco_StringChannel*)GetChild(1);

    if(pipeexist){// Konnte die Pipe erstellt werden<<

    if (stringchannel != NULL) {
    stringchannel->SetString(temp2);
    }}
    else{
    if (stringchannel != NULL) {
    stringchannel->SetString(temp);
    }}

    if(result){
    buffer[numBytesRead / sizeof(wchar_t)] = '\0';
    mybuffer[numBytesRead / sizeof(wchar_t)] = '\0';

    size_t mychar = (size_t)numBytesRead / sizeof(wchar_t);
    size_t mysize = wcstombs(mybuffer,buffer,mychar);

    if (stringchannel2 != NULL) {
    stringchannel2->SetString(mybuffer);
    }

    }

    Was mache ich denn falsch? 😕

    Gibt es denn eine andere Möglichkeit eine Kommunikation zwischen der dll und c++ aufzubauen? Ich habe mir ein Beispiel über Wrapper Klassen angeschaut, aber nichts verstanden!

    Über Hilfe wäre ich dankbar!



  • Schau mal hier:

    if (CheckRenderCount()) { 
    result = ReadFile( 
    pipe, 
    buffer,
    127 * sizeof(wchar_t), // <<<<------ number of bytes allocated 
    &numBytesRead,
    NULL 
    );
    

    Was ich aber nicht verstanden habe: Warum C#, VB und C++ ?
    Klingt so als ob du das sehr umständlich löst. Warum überhaupt den Umweg über ein weitere Programmiersprache ?
    Was genau versuchst du zu erreichen ?



  • Hallo!

    Leider bin ich gezwungen eine Lösung über mehrere Programmiersprachen zu finden.
    Die dll ist in Visual Basic geschrieben. Diese wollte ich mit Hilfe einer c# Klasse einbinden, weil das funktioniert.

    Die Entwicklungsumgebung, die ich benutze verlangt als Programmiersprache c++.
    Deshalb der Weg über mehrere Programmiersprachen!

    Aber was meinen Sie in Bezug auf die Angabe des c++ Fragments? Liegt da der Fehler?

    127 * sizeof(wchar_t)!!!!

    if (CheckRenderCount()) {
    result = ReadFile(
    pipe,
    buffer,
    127 * sizeof(wchar_t), // <<<<------ number of bytes allocated
    &numBytesRead,
    NULL
    );
    


  • konkret schrieb:

    Aber was meinen Sie in Bezug auf die Angabe des c++ Fragments? Liegt da der Fehler?

    <a href= schrieb:

    MSDN: ReadFile">BOOL WINAPI ReadFile(
    _In_ HANDLE hFile,
    _Out_ LPVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToRead,
    _Out_opt_ LPDWORD lpNumberOfBytesRead,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );

    nNumberOfBytesToRead [in]
    The maximum number of bytes to be read.

    Ergo: Ja. Du ließt immernoch nur 127 Bytes, ergo steht in den restlichen Bytes nur Schrott. Drum auch die fehlerhafte Ausgabe.

    konkret schrieb:

    Die dll ist in Visual Basic geschrieben. Diese wollte ich mit Hilfe einer c# Klasse einbinden, weil das funktioniert.

    DLLs kannst du mit (fast) jeder Programmiersprache nutzen. C++ gehört da auch dazu. 😉
    Der Umweg über C# macht das ganze doch nur wahnsinnig kompliziert.
    Wieviele Funktionen willst du denn nutzen ?
    Ich würde zu einer C++ Wrapperklasse und dort LoadLibrary und GetProcAddress raten. Das geht auch wenn du keine .lib hast sondern nur die DLL. Und die Funktionssignaturen hast du ja.



  • DarkShadow44 schrieb:

    konkret schrieb:

    Die dll ist in Visual Basic geschrieben. Diese wollte ich mit Hilfe einer c# Klasse einbinden, weil das funktioniert.

    DLLs kannst du mit (fast) jeder Programmiersprache nutzen. C++ gehört da auch dazu. 😉

    Er hat aber keine DLL, sondern eine .NET Assembly.



  • hustbaer schrieb:

    Er hat aber keine DLL, sondern eine .NET Assembly.

    Ach stimmt das war ja schon .NET...
    Aber trotzdem ist er Umweg über C# zuviel. Wenn schon hostet man die CLR, oder nimmt gleich C++/CLI.



  • Hallo!

    Ich habe das mal geändert!

    128 * sizeof(wchar_t)
    

    Aber leider kommt der gleiche Fehler! Ich habe auch die Größe des zu übertragenden String auf 128 Zeichen erhöht, aber der gleiche Fehler. Nur "i"'s

    Oder habe ich etwas falsch verstanden? 😕

    Gruss



  • DarkShadow44 schrieb:

    hustbaer schrieb:

    Er hat aber keine DLL, sondern eine .NET Assembly.

    Wenn schon hostet man die CLR,

    lol
    Was soll das denn bringen?

    DarkShadow44 schrieb:

    oder nimmt gleich C++/CLI.

    Mhm.
    Na dann hätten wir das jetzt auch geklärt. Wunderbar, wieder eine Frage weniger auf die die Welt eine Antwort sucht.


Anmelden zum Antworten