2011-01-14 23 views
7

Tôi có một giao diện điều khiển C++ Exe mà hiện một số progamming. Bây giờ tôi muốn viết một C# GUI mà hiện một số các chương trình mà exe C + + không. Tôi đã nghĩ đến vài phương pháp tiếp cận,Soạn thảo C# GUI trên một dll C++ hoặc C++ exe

  1. Viết C# GUI với tất cả các chương trình trong C++ thực hiện từ đầu. (Tôi không muốn làm điều này với số tiền là làm lại nó đòi hỏi)
  2. Xây dựng một C++ dll mà Hiện nay tôi có một mối quan tâm.Làm thế nào để tôi nắm bắt đầu ra của các thói quen trong c + + dll và hiển thị nó trong GUI? Tôi có nên trả lại đầu ra như chuỗi cho mọi thói quen mà các ứng dụng cuộc gọi.? Vì tôi không biết quản lý c + + iam sẽ xây dựng một không được quản lý C + + dll.)
+0

bạn đã xem xét thêm một giao diện COM? Kể từ đó, IMHO, thông qua các đối số và dữ liệu chương trình với các thùng chứa COM có thể là giải pháp. –

Trả lời

7

Xây dựng một C++/CLI dll thực sự không phải là khó. Về cơ bản, bạn sử dụng mã C++ không được quản lý ngoại trừ việc bạn định nghĩa một "public ref class", nó lưu trữ các hàm bạn muốn mã C# để xem.

Bạn đang quay trở lại loại dữ liệu nào? Số đơn, ma trận số, đối tượng phức tạp?

CẬP NHẬT: Vì đã được làm rõ rằng "đầu ra" là iostreams, here is a project thể hiện chuyển hướng cout sang ứng dụng .NET gọi thư viện. Chuyển hướng clog hoặc cerr sẽ chỉ yêu cầu một số dòng bổ sung trong DllMain được tạo hoa văn sau chuyển hướng hiện có.

The zip file bao gồm các file project VS2010, nhưng mã nguồn cũng nên làm việc vào năm 2005 hoặc 2008.

Chức năng chụp iostreams được chứa trong đoạn mã sau:

// compile this part without /clr 
class capturebuf : public std::stringbuf 
{ 
protected: 
    virtual int sync() 
    { 
     // ensure NUL termination 
     overflow(0); 
     // send to .NET trace listeners 
     loghelper(pbase()); 
     // clear buffer 
     str(std::string()); 
     return __super::sync(); 
    } 
}; 

BOOL WINAPI DllMain(_In_ HANDLE _HDllHandle, _In_ DWORD _Reason, _In_opt_ LPVOID _Reserved) 
{ 
    static std::streambuf* origbuf; 
    static capturebuf* altbuf; 
    switch (_Reason) 
    { 
    case DLL_PROCESS_ATTACH: 
     origbuf = std::cout.rdbuf(); 
     std::cout.rdbuf(altbuf = new capturebuf()); 
     break; 
    case DLL_PROCESS_DETACH: 
     std::cout.rdbuf(origbuf); 
     delete altbuf; 
     break; 
    } 

    return TRUE; 
} 

// compile this helper function with /clr 
void loghelper(char* msg) { Trace::Write(gcnew System::String(msg)); } 
+0

Tôi muốn hiển thị các thông điệp tường trình xuất phát từ DLL C++ trong GUI C#. – excray

+0

@ user97642: Vì vậy, các C + + DLL là văn bản để 'std :: clog' và bạn muốn gửi đầu ra này để C#? –

+0

Có làm tắc nghẽn hoặc cout hoặc cerr. – excray

3

Vì vậy, bạn chỉ muốn gọi thư viện C++ từ mã .net được quản lý?

Sau đó, bạn sẽ cần xây dựng một đối tượng COM hoặc thư viện không thể xâm nhập p trong C++. Mỗi phương pháp đều có ưu và nhược điểm riêng tùy thuộc vào nhu cầu kinh doanh của bạn. Bạn sẽ phải marshall dữ liệu trong người tiêu dùng của bạn. Có tấn và tấn vật liệu trên cả hai khái niệm.

0

Bạn chỉ có thể viết trình bao bọc C# GUI (như bạn đề xuất trong tùy chọn 2) và sinh ra quy trình C++; tuy nhiên, điều này sẽ hơi chậm (tôi không biết điều đó có quan trọng không).

Để chạy bản exe C++ của bạn và nắm bắt đầu ra, bạn có thể sử dụng ProcessRunner mà tôi đặt cùng nhau. Dưới đây là cách sử dụng cơ bản:

using CSharpTest.Net.Processes; 
partial class Program 
{ 
    static int Main(string[] args) 
    { 
     ProcessRunner run = new ProcessRunner("svn.exe", "update"); 
     run.OutputReceived += new ProcessOutputEventHandler(run_OutputReceived); 
     return run.Run(); 
    } 

    static void run_OutputReceived(object sender, ProcessOutputEventArgs args) 
    { 
     Console.WriteLine("{0}: {1}", args.Error ? "Error" : "Output", args.Data); 
    } 
} 
+0

Tôi đang tìm cách tìm ra tùy chọn thứ hai. Một C# GUI sử dụng một DLL C++. – excray

0

Có lẽ cách tốt nhất để đi ở đây là sử dụng P/Invoke hoặc nền tảng Gọi. Tùy thuộc vào cấu trúc hoặc giao diện dll C++ bạn có thể muốn bọc nó trong một giao diện C thuần túy; nó là dễ nhất nếu giao diện của bạn chỉ sử dụng các loại blittable. Nếu bạn giới hạn giao diện dll của bạn thành các loại blittable (Int32, Single, Boolean, Int32 [], Single [], Double [] - khái niệm cơ bản), bạn sẽ không cần phải thực hiện bất kỳ việc điều chỉnh phức tạp dữ liệu giữa được quản lý (C#) và không được quản lý (C) không gian bộ nhớ.

Ví dụ: trong mã C# của bạn, bạn xác định các cuộc gọi có sẵn trong dll C/C++ bằng thuộc tính DllImport.

[DllImport, "ExactDllName.dll"] 
static extern boolean OneOfMyCoolCRoutines([In] Double[] x, [In] Double[] y, [Out] Double result) 

Ít [In] và [Out] không bắt buộc, nhưng chúng có thể tăng tốc. Bây giờ bạn đã thêm "ExactDllName.dll" của bạn làm tham chiếu đến dự án C#, bạn có thể gọi hàm C/C++ từ mã C# của bạn.

fixed(Double *x = &x[0], *y = &y[0]) 
{ 
    Boolean returnValue = OneOfMyCoolCRoutines(x, y, r); 
} 

Lưu ý rằng tôi về cơ bản sẽ chuyển con trỏ ngược lại và thứ tư giữa dll và mã C# của tôi. Điều đó có thể gây ra lỗi bộ nhớ vì các vị trí của các mảng đó có thể được thay đổi bởi bộ thu gom CLR, nhưng C/C++ sẽ không biết gì về nó. Vì vậy, để bảo vệ chống lại điều đó, tôi đã chỉ đơn giản là cố định những con trỏ trong C# của tôi, và bây giờ họ sẽ không di chuyển trong bộ nhớ trong khi dll của tôi đang hoạt động trên các mảng. Đây là mã không an toàn và tôi sẽ cần biên dịch mã C# của tôi với cờ đó.

Có nhiều chi tiết tinh tế để tương tác với ngôn ngữ, nhưng điều đó sẽ giúp bạn phát triển. Gắn bó với giao diện C không trạng thái của các loại blittable là một chính sách tuyệt vời nếu có thể. Điều đó sẽ giữ mã ngôn ngữ interop của bạn sạch sẽ nhất.

Chúc may mắn,

Paul

Các vấn đề liên quan