Writing a C # GUI over a C ++ dll or C ++ exe

I have an exex console that does some progaming. Now I wanted to write a C # GUI that runs some of the programs that C ++ exe runs. I was thinking of several approaches,

  • Write a C # GUI with all C ++ programs made from scratch. (I do not want to do this in order to introduce additional refinement into it)
  • Create a C ++ dll that does the programming and imports it into a GUI application. (Now I have a problem. How can I capture the output of the routines in the C ++ dll and display it in the GUI? Should I return the result as a string for each procedure that the application calls. Since I do not know what managed C ++ is iam is going to create an unmanaged C ++ dll.)
+7
source share
6 answers

Building a C ++ / CLI dll is really not that difficult. Mostly you use unmanaged C ++ code, except that you define a " public ref class " that hosts the functions you want to see in C #.

What data do you return? Single numbers, matrixes of numbers, complex objects?

UPDATE: Since it was clarified that the β€œexit” is iostreams, here is a project demonstrating redirecting cout to a. NET by calling the library. A clog or cerr will only require a few extra lines in the DllMain formed after the existing redirect.

The mail file includes the VS2010 project files, but the source code should also work in 2005 or 2008.

The iostreams capture function is contained in the following code:

 // 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)); } 
+7
source

So, you just want to call the C ++ library from managed .net code?

Then you need to either build a COM object or a p-invokable library in C ++. Each approach has its pros and cons depending on the needs of your business. You will need to sort the data from your consumer. There are tons and tons of material for both concepts.

+3
source
0
source

You can simply write the C # GUI shell (as you suggest in option 2) and start the C ++ process; however this will be a little slow (I don't know if that matters).

To run C ++ exe and grab the output, you can use the ProcessRunner that I put together. Here is the main use:

 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
source

See the first comment on this page for redirecting stderr

0
source

Probably the best way here is to use P / Invoke or Platform Invoke. Depending on the structure or interface of the C ++ dll, you can wrap it in a clean C interface; this is easiest if your interface uses only blittable . If you restrict your dll blittable interface to types (Int32, Single, Boolean, Int32 [], Single [], Double [] - the basics), you do not need to perform complex data marshalling between managed (C #) and unmanaged (C).

For example, in C # code, you define the available calls in your C / C ++ dll using the DllImport attribute.

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

Small [In] and [Out] are not strictly required, but they can speed things up. Now by adding your "ExactDllName.dll" as a link to your C # project, you can call your C / C ++ function from your C # code.

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

Note that I essentially pass pointers back and the fourth between my dll and C # code. This can lead to memory errors, since the location of these arrays can be changed by the CLR garbage collector, but the C / C ++ dll will not know anything about it. Therefore, to protect myself from this, I just fixed these pointers in my C #, and now they will not move in memory, while my dll works on these arrays. This is now unsafe code, and I will need to compile C # code with this flag.

There are many small details for language interaction, but this should make you go for a ride. Sticking to a stateless C-interface of blittable types is a great policy, if possible. This will allow your language to intercept the cleanest code.

Good luck

Floor

0
source

All Articles