OP:
Is there any way to integrate Steam DRM with a C# game?
Directly? No. Indirectly? Yes. Let me explain...
What you really want to know is how can c# code call c++ and the answer is yes. Tell me more. If you look at the link, the best answer is to modify the c++ code to change it to a hybrid c++/CLI DLL. Since that's not possible with the Steam provided API, the alternative is to create a proxy.
The thing to do (since you can't modify the c++ DLL) is create a new c++/CLI DLL (let's call it Proxy) that calls the Steam C++ DLL (S) on your behalf. This gets around the problem of p-invoking a c++ DLL which is subject to name mangling as opposed to a c DLL which does not. Proxy exposes classes that are a mix of c++ and .NET. Your app calls what it thinks is just .NET code inside the proxy. Proxy then calls the raw c++ code in S.
Call sequence goes like this:
App --> Proxy --> S
If you notice you will learn that the proxy is really just your own wrapper - a very simple one for the specific functions your app is interested in, so again the reliance for a 3rd party wrapper does not seem worth it considering the risk. There should not be any special and/or complex business logic in your proxy. Keep it simple. Be sure to keep your copy of the steam code/libs up to date with Steam's latest API.
OP:
but there are wrappers like SteamWorks.Net für C#. However, as far as I know, these only support major features (like cloud save and achievements) but that do not support Steam DRM
Personally I wouldn't want to rely on a potentially unproven; subject to becoming out of sync with Steam changes; 3rd party open source project for something as important as DRM so my advice is stick with SteamWorks proper.
What's c++/CLI?
Briefly, c++/CLI is a Microsoft technology that has been around for some time now that allows you to create a hybrid c++ and .NET DLL. Your code has access to .NET as well as the wealth of historic c/c++ code and libs. .NET code can call public CLR types in the hybrid dll.
More
- name mangling - a somewhat annoying aspect of c++ compilers that turn method names like
bool article::print_to (std::ostream&)
into _ZN9wikipedia7article8print_toERSo
for many reasons, one of which is for the need of unique naming, but have the unwanted side effect of making it difficult to determine which export is the entry to p-invoke.