This chapter has shown you some of the complexity that can arise when using Platform Invoke to call unmanaged code. You have seen how to control the way in which strings, arrays, and structures are passed between managed and unmanaged code, and you have been introduced to the MarshalAs attribute and its uses.
C++ poses particular problems when interacting between managed and unmanaged code because of its use of pointers. The chapter discussed the use of the GCHandle type and the gcroot template class, and it showed how you can make sure managed objects will not be collected by the garbage collector when they are being used only in unmanaged code.
Most Platform Invoke calls are defined at compile time, but you saw how to influence the choice of DLL, and I mentioned that it is also possible to completely build a Platform Invoke method at run time.
The next chapter completes our look at interoperability by showing how you can work with predefined COM interfaces by defining managed equivalents.