Introduction to Interoperability in C#
Interoperability enables you to leverage your existing investment in unmanaged code going forward with the .NET Framework. Unmanaged code consists of all code that is not managed and executed within the Common Language Runtime (CLR). This includes COM objects, C++ DLLs, ActiveX controls, COM+ components, and any other code that is not compiled.
As you will find out, there are two different kinds of interoperability in C#, interoperability with unmanaged DLLs and interoperability with binary COM objects. Each is accomplished using a different technology, but some aspects of interoperability remain the same regardless of whether you're working with unmanaged DLLs or COM objects.
One of the things that remain the same is the need for reliable transfer of data. A common problem among developers before managed code was not being able to write code in one language that could communicate with code written in another language. For example, a C string was stored in memory as an array of bytes terminated by the ASCII null (\0) character. What is called a "Pascal string" is an array of bytes where the length of the string is stored in the 0th element of that array. As you can imagine, you can't simply pass a string from Pascal to C or from C to Pascal without modification.
The same is true of managed and unmanaged code. The process by which data is transferred between managed and unmanaged environments is called marshaling. This process is what converts .NET types into types that will be recognizable by unmanaged code and vice versa. As you'll see in the code samples that follow, there are tools that can determine how to marshal data from one environment to the other when reading and writing things like COM type libraries, but you still may need to know ahead of time how the data will need to be marshaled in order to consume unmanaged code from within .NET.