In my C# application, I would like to write a part of the code in C. I plan to write a DLL witch would be interoperable with .Net. How can I do that?
4 Answers
There are essentially three right ways to do it:
- Use C++/CLI. This is the optimal way if this DLL is going to be used only by .NET.
- Use an "
extern "C"
" compatible API, like the Windows API itself. This is the most portable, but isn't as convenient for your callers as using a class model to represent your objects.- This is the best option if you really intend to write in ANSI C (not C++).
- For this path, you write your functions as
extern "C" returntype __stdcall __declspec(dllexport) func(params) { ... }
- You should also use a "caller-provides-the-buffer" memory model, rather than returning a buffer allocated inside your library. In the cases where you do need to allocate memory for internal state, the caller should see it as an opaque handle and you should provide accessor functions for the caller to extract data. Under no circumstances should the caller be expected to deallocate memory allocated inside your library, however it is ok for the caller to ask the library to do the deallocation.
- Use COM, or a COM-like API. Here you return (often via out parameter) a pointer to an interface, which is a class with pure virtual functions, no non-virtual functions and no data.
- The implementation is in concrete classes derived from this abstract interface, they can have data and helper functions galore, since that doesn't affect the binary interface.
- This is a lot more work in the library but extremely portable and easy for the consumer to use.
And there is one thing absolutely NOT to do:
- use
__declspec(dllexport)
on C++ classes.
EDIT: I want to also explain some good practices for option #2 which will maximize portability and make the native C/C++ parts usable from unmanaged applications as well.
You can make that easier with a macro, the usual way of doing it is:
In your header file, all the function declarations look like
MYPROJECTAPI(returntype) PublicFunc(params);
In your project, the definition is
#define MYPROJECTAPI(returntype) \
extern "C" returntype __stdcall __declspec(dllexport)
In consumer projects
#define MYPROJECTAPI(returntype) \
extern "C" returntype __stdcall __declspec(dllimport)
and then you can define the macro differently for other compilers like gcc which don't use __declspec
.
The complete solution would look like (in public header file myproject.h
):
#if _WIN32
# if BUILDMYPROJECT
# define MYPROJECTAPI(returntype) \
extern "C" returntype __stdcall __declspec(dllexport)
# else
# define MYPROJECTAPI(returntype) \
extern "C" returntype __stdcall __declspec(dllimport)
# endif
#else
# define MYPROJECTAPI(returntype) extern "C" returntype
#endif
and then your Visual C++ project would cause BUILDMYPROJECT
to be defined when building myproject.dll

- 277,958
- 43
- 419
- 720
-
how can create a C++/CLI project with visual studio 2010? – Martin Delille Sep 16 '10 at 14:23
-
File -> New -> Project, then Visual C++ -> CLR -> Class Library – Ben Voigt Sep 16 '10 at 15:56
-
It does'nt build. I have the followind error: 2 error TRK0005: Failed to locate: "CL.exe". – Martin Delille Sep 16 '10 at 16:04
-
1Rerun the Visual Studio 2010 installer, make sure you selected to install Visual C++ tools for your platform (either x86 or amd64). You might need the installer repair mode. – Ben Voigt Sep 16 '10 at 16:05
-
It was hard find this link, so I want to share it here (I do NOT work for this company!): http://www.xinterop.com/index.php/2015/04/30/introduction-to-the-xinterop-net-bridge/ – Niklas Peter Sep 06 '15 at 17:20
-
1"And there is one thing absolutely NOT to do:" Please support this statement with reasons. – Niklas Peter Sep 06 '15 at 17:22
-
I'd also like to know why that is: "And there is one thing absolutely NOT to do:" – Toastgeraet Feb 03 '16 at 10:25
-
1@NiklasPeter: Read http://stackoverflow.com/a/22797419/103167 and then consider that you're making it even *more* complex by adding .NET into the mix. – Ben Voigt Feb 03 '16 at 14:37
In a nutshell:
(1) Create a new C++/CLI library project.
(2) Write your code. For classes that need to be accessible from your C# project, make sure to create them as CLR classes:
public ref class R {/*...*/}; // CLR class
public value class V {/*...*/}; // CLR struct
public interface class I {/*...*/}; // CLR interface
(3) Compile the project and add a reference to it in your C# project.

- 167,459
- 57
- 363
- 519
-
how can create a C++/CLI library project with visual studio 2010? – Martin Delille Sep 16 '10 at 14:23
-
@tinmaru: I don't have VS 2010 installed right now, but according to MSDN (http://msdn.microsoft.com/en-us/library/0fyc0azh.aspx), there should be a "CLR/Class Library" project template available. – Heinzi Sep 16 '10 at 15:01
Through P/Invoke layer.

- 1,296
- 10
- 13
-
This doesn't help with the DLL-writing process *at all*, which is what the question is about. – Ben Voigt Sep 16 '10 at 13:05
-
Ok. My understanding is that he was asking for a way to communicate with C/C++ dll from .NET. P/Invoke layer does that work. – Adi Sep 16 '10 at 13:12
-
The way I parse the question is "How do I do that [write a DLL which would be interoperable]?" – Ben Voigt Sep 16 '10 at 15:54
-
Below is an example for an application where I had to do just that. In my case, I needed a DLL to wrap calls to functions that were only available in a .lib. The key part is the extern "C" __declspec (dllexport)
in the declaration. That's basically all you need. The rest was merely using dllimport
in the C# app and getting the marshalling right.
extern "C" __declspec (dllexport) LONG EstablishContext(DWORD dwScope,
LPCVOID pvReserved1,
LPCVOID pvReserved2,
LPSCARDCONTEXT phContext)
{
return SCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
}

- 13,328
- 13
- 64
- 78
-
Don't forget `__stdcall` (or equivalently, use the `WINAPI` macro). This will simplify the p/invoke declarations considerably. – Ben Voigt Sep 16 '10 at 13:00