43

Is it a good idea to combine C++ and C# or does it pose any immediate issues?

I have an application that needs some parts to be C++, and some parts to be C# (for increased efficiency). What would be the best way to achieve using a native C++ dll in C#?

4 Answers 4

51

The question is clearly how to integrate his own C++ code to his C# solution, not just what attribute to use in order to call an existing function from the win32 API. Even if the answer was already accepted, I think it's incomplete, and the following should apply.

Yes, it is common practice in the cases where the task can either run faster, use less resources, and also in some cases to access methods that are not available in the .net framework.

If your goal is to gain efficiency you need to code a native unmanaged C++ library, you will create a new unmanaged C++ project (that compiles as a dll library) in visual studio and reference this library from your C# project.

In your case it seems you might be writing an unmanaged C++ library, and the following applies.

As for any immediate issues you were asking about, it would impact deployment and obfuscation.

  • Deployment: Keep in mind that the C# DLLs you build will run on any CPU, both 32 and 64bit, but this new native and unmanaged C++ library will force your program to be either for 32 or 64 specific.

    This is something you will configure in your Visual Studio configuration manager, and will be taken care of at compile time, you will pick AnyCPU for C# assemblies and for your new unmanaged C++ library, which will be in it's own project, you will have to choose from win32 or x64.

    So you will now have 2 setups, it is recommended best practice to have separate setups, one for 32 and another one for 64. Or since 32bit support is dropping very fast, you could focus on 64bit only.

    Also, your library might end up referencing the VC++ redistibutable provided by Visual Studio, which you might have to include in your deployment, although some version of it are included on many OS, I found it's rarely the same one I compiled with and it's best to deploy it with your application to be sure. If this pack is missing, the target machine will have a SideBySide exception in the eventviewer->application log.

    To catch and handle an exception thrown from unmanaged code, the only catch that works is the empty one, the one with no exception type in the parenthesis after the catch(). So you can wrap your calls to unmanaged code in this to handle all unmanaged exceptions thrown from inside the unmanaged code, if you put a .net type like catch(Exception), it will just jump over it. The only way to catch an unmanaged exception, inside managed code is in this format.

 try { //call unmanaged code } catch { //handle unmanaged exception } 

  • Obfuscation: Any method calls done from C# that are now calling unmanaged code will now be excluded from renaming automatically. And on the flip side, if your unmanaged C++ library needs to call methods from your managed assemblies, those will need to be excluded from renaming, manually, in order to be visible to the C++ library calling them.

If what you need is only to call well known C++ libraries like the Windows ones, you will NOT need to create a new unmanaged C++ project, only use the [DllImport()] attribute suggested in a previous answer. And in this case you could take a look at this reference http://www.pinvoke.net/

Sign up to request clarification or add additional context in comments.

1 Comment

catch and handle an exception thrown from unmanaged code -- I think this has to be rephrased, catch without exception type specification means only to catch exceptions. There is no easy way for specific handling, but catching keeps your C# application running... See also .net - Can you catch a native exception in C# code? - Stack Overflow and CA2102: Catch non-CLSCompliant exceptions in general handlers
45

Yes using C# and C++ for your product is very common and a good idea.

Sometimes you can use managed C++, in which case you can use your managed C++ module just like any other .NET module.

Typically you'd do everything that you can in C#. For the parts you need to do in C++ you'd typically create a C++ DLL and then call into that DLL from C#. Marshalling of parameters is done automatically for you.

Here is an example of importing a C function inside a DLL into C#:

[DllImport("user32", CharSet=CharSet.Auto, SetLastError=true)] internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount); 

8 Comments

Is that advertising for .NET? What about cross-platform compatibility, connection issues, learning curve, etc.?
Learning curve? I suppose you know basics of both C++ and C# when trying to combine languages. Cross platform? It's obvious writing cross platform code in C++ is much harder, but possible. Seems even a little easier when combined with C# - a higher level code can decide WHICH C/C++ parts to load and use on a specific platform.
I sure hope you aren't using C++ to target a PIC!
@Harry "` It's obvious writing cross platform code in C++ is much harder, but possible`" ???? O'Rly? In what way is that obvious?
Because of manual memory management being platform dependent. Then, GC in C# does some serious amount of work. Doing the work manually instead seems to be harder. Configuration of a C# project is trivial. Configuring even basic compiler options for C++ is not trivial. Changing target architecture from let's say x86 to x64 is switching one option in C# project. Of course we have platform dependent code in C# too, but much more basic things is pretty much platform independent. C# has also many smart features way more modern than macros.
|
0

The accepted answer is incorrect because the question is about native C/C++, managed C/C++ is a very different story.

The MS VS does not allow to combine unmanaged and managed projects together in one solution.

But there is some trick: you need to know what a solution file is, how it is formatted and composed. So, you need to create a solution file manually.

The main point is: the VS recognizes a project type by NOT an extension of the file name or even by parsing its content, this is the work for MSBuild. There are some sort of registered project type GUIDs that are accepted by VS, one of them is for simple folder nodes, others for VC++ and C# projects respectively.

This is excerpt from real solution file:

Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp_template.con", "cpp\cpp_template.con.vcxproj", "{00000C13-EEEE-BBBB-6667-000000000020}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csh_template.con", "net\csh_template.con.csproj", "{00000C13-EEEE-BBBB-6667-CAA000000000}" EndProject 

C++ native and C# projects can be very friendly to each other. :D

The complete description of the genetic solution file is in this document mix_proj_in_vs_sln.doc, but if you do not want to waste your time reading this file there is a solution that includes simple projects: C# and C++ console apps. It was created in VS 2017, can be downloaded and built.

Comments

-7

Additional information about C# versus C++ differences and possibles issues merging them:

  • C# is an interpreted, like Java. C++ is compiled to native binary. That carry several differences explained further in following points. Even when using JIT, it requires the initial stage of translation.
  • Platform compatibility: C#, as interpreted and a Microsoft product, it works fine on Windows, correctly on Linux thanks to a great project Mono, but not that well (or not at all) on other platforms (Android, IOS, others.) If you want to write software for embedded where there is no support of an operating system, or to write an OS itself, you mostly "cannot" use C#. C++ is totally cross-platform as soon as you have a compiler (which is usually the case).
  • Interpreted code is usually one order of magnitude slower than binary code[1]. That is one reason of linking C++ in your C#.
  • Binary vs intermediate code: Intermediate code work on any interpreter available on a specific architecture, C++ require recompiling for each architecture.
  • Learning curve: In order to combine both languages, Developer are required to learn several languages, which increase learning time. It is also harder to found experts in both languages.
  • Real-time: It seem difficult to imagine (hard) real-time conditions with C#.
  • Some quality certifications could be impossible to get with C# code (safety critical software).

Is it a good idea to combine them?

That probably depends of your project. For large HMI development on Windows (or even Linux), this is likely to improve your development time. But, other software requirements could restrict from using C# in favour of C++ (or ASM, C, ..).


[1] I read many times that interpreted code is in some case even faster than binary code, this is due to a misconception: The interpreter implements several functions for convenience, so when you call (e.g.)sort(), in reality it call a binary implementation of this function. If this function is well optimized, the final time could be faster, but just because all run in binary and the interpreted component is minimal compared to all the time required to sort. On the other side, if you code a full logic in both languages, the binary version will always be significantly faster. The reason is simple: an interpreter IS a binary which run, in addition of your code, all the language framework.

5 Comments

Jit is not the same as interpreted. Jit can compile to machine code.
Jit is compiled run-time -> that require time too. It does not work on, let's say a PIC16F, it cannot be certified, etc.
The negative score is because of some reason?
Mostly because almost everything in your answer is false. JIT isn't interpretation. C# can be fully compiled in advance instead of using JIT, C# runs on Linux without Mono, C# can be developed from any editor, C++ can't do realtime any better than C# because both are running on a time-sharing OS, and C# code can be certified for medical and aerospace applications.
JIT isn't interpretation but is translated at run-time right? C# can not be developed on Linux without Mono, so not really cross-platform right? C++ can do hard real-time, for example by running on a RTOS; did you tried to run C# on an RTOS, MCU or driver (I did for C++)? And please, tell me about any Safety-critical software in C#. Not saying C# is bad, but it has it limitations too.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.