开发者

Combining C++ and C#

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 开发者_如何学Gobe C# (for increased efficiency). What would be the best way to achieve using a native C++ dll in C#?


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/


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);


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜