2016-08-03 26 views
0

zu verwenden Ich muss meinen C++ Code in C# Anwendung benutzen. Ich dachte über Pinvoke nach, aber ich bin verwirrt mit dem Ansatz, den ich für die Erstellung von DLL aus meiner C++ App nehmen sollte. Grundsätzlich ist meine C++ App eine main Funktion, die eine Endlosschleife der Datenverarbeitung ausführt und ich weiß nicht, wie ich so etwas in dll exportieren und es von C# aufrufen kann.Wie man Funktion für dll (C++) von der Hauptfunktion herstellt, um in C#

Ich versuchte, meine main Funktion im Standalone-init Funktion für DLL und rufen sie von C# neu zu schreiben, sondern weil es eine Endlos-Schleife dazu kam es nicht von der Funktion mit return auf den Punkt. Und ich weiß nicht, wie ich meinen Datenpuffer irgendwann von Endlosschleife zu meiner C# -App bekomme.

Was ich zur Zeit getan:

// myDLL.cpp 
int __stdcall OpenRTSP(char url, char progname) 
{ 
    TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 
    UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); 

    if (openURL(*env, &progname, &url) < 0) 
    { 
     return -1; 
    } 

    // All subsequent activity takes place within the event loop: 
    // This function call does not return, unless programm closes. 
    env->taskScheduler().doEventLoop(&eventLoopWatchVariable); 

    return 0; 
} 

// myDLL.h 
__declspec(dllexport) int __stdcall OpenRTSP(char url, char progname); 

Ich weiß nicht, wie OpenRTSP von C# nennen, weil sie nie von diesem func zurückkehren und wie eine Funktion zu schreiben, die mir einen Datenpuffer zurück von der Endlosschleife?

Antwort

1

Da Ihr C++ - Programm einen kontinuierlichen Prozess ausführt, sollten Sie besser einen eigenständigen Prozess erstellen und ihn unter Verwendung von Process class von Ihrem C# -Code aus ausführen. Die Daten aus Ihrem C++ - Prozess können aufgrund einiger IPC-Methoden übergeben werden. Der einfache STDOUT scheint Ihrer Aufgabe ziemlich gut zu entsprechen. This post beschreibt, wie es erreicht werden kann.

Hier ist ein kurzes Codebeispiel:

var cppProcess = new Process(); 
cppProcess.StartInfo = new ProcessStartInfo 
{ 
    FileName = "YourCppApp.exe", 
    UseShellExecute = false, 
    RedirectStandardOutput = true, 
}; 
cppProcess.OutputDataReceived += (sender, arg) => 
{ 
    Console.WriteLine("Received: {0}", arg.Data); 
}; 
cppProcess.Start(); 
cppProcess.BeginOutputReadLine(); 

Wenn der Puffer Sie zurück von den C++ App senden eher binär sein sollte, verwenden BinaryReader aus dem C++ App STDOUT zu lesen:

var cppProcess = new Process(); 
cppProcess.StartInfo = new ProcessStartInfo 
{ 
    FileName = "YourCppApp.exe", 
    UseShellExecute = false, 
    RedirectStandardOutput = true, 
}; 
cppProcess.Start(); 
using (var cppOutput = new BinaryReader(cppProcess.StandardOutput.BaseStream)) 
    while (!cppProcess.StandardOutput.EndOfStream) 
    { 
     var buffer = new byte[4096]; 
     int bytesRead= cppOutput.Read(buffer, 0, buffer.Length); 
     // Process the buffer... 
    } 

Alternativ können Sie Ihre main Funktion in eine Bibliotheksfunktion ändern, wie Sie es bereits versucht haben, und eine Rückruffunktion von C# als Parameter übergeben. Aber das wäre mühsamer und ich persönlich würde das in Ihrem speziellen Fall nicht tun.

+0

Nach einiger Arbeit habe ich festgestellt, dass Standalone-Prozess ist viel schneller als 'dllimport' Weg. Danke für die Hilfe. Außerdem, um Dinge für andere Leute zu klären - Ich habe es mit Pipe-Datentransfer zwischen C++ und C# getestet. – Aleksey

0

Wenn die Funktion, die Sie benötigen, tatsächlich main() ist und Sie nicht mit Ihrer C# -Anwendung interagieren müssen, können Sie Ihre ausführbare Datei als externen Prozess ausführen. Sehen Sie in der Dokumentation von System.Diagnostics.Process wie das geht.

Wenn dies nicht die richtige Option für Sie ist, dann versuchen Sie, Ihre Sperrfunktion über P/Invoke aus einem separaten Thread aufzurufen.

0

Erstellen Sie ein CLR-Projekt und importieren Sie es in C#, wenn Sie den vollen C++ - Code haben, ist das kein Problem.

Um es nur zu tun: Neues Projekt-> C++ -> CLR-> Klassenbibliothek. Dann auf den Header schreiben Sie etwas wie folgt aus:

// filename.h 
#pragma once 

using namespace System; 

namespace YourNampespace 
{ 
    public ref class YourClass abstract sealed 
    { 
    //int __stdcall OpenRTSP(char url, char progname); 
    //You want to convert this to managed, buf if you return "int", with "char" params, 
    // it won't be a problem 
    } 
} 

Dann auf der Quelldatei:

#include "stdafx.h" 
#include "filename.h" 
int YourNampespace::YourClass::__stdcall OpenRTSP(char url, char progname) 
{ 
//Code here 
} 

Ich kenne fast keine C++, und ich bin nicht sicher, was meinst du "endless loop of data processing" ¨, aber Sie könnten schreiben, welche Daten an einen Stream gesendet werden, geben Sie sie an die C# -App zurück und lesen Sie sie von dort.Keine Interprozess-Dinge (ich denke, das würde mehr Probleme bringen)