IIS7 core extensibility model supports both native and managed code as first-class citizens. So, I feel it is time for a little refresher on managed/native code interop... starting with the more popular route of how to wrap native code API for use within managed code. I am using the newer syntax introduced with .Net Framework 2.0 instead of the older, kludgy syntax.

Now, I am going to ignore the reciprocal route of calling managed code from native code for a couple of reasons:

  • It is just boiler plate COM Interop within native code after generating and registering the CCW (COM Callable Wrapper) of the managed class.
  • Why don't you just write a managed code module/handler in IIS7 to directly use that managed API?

The example illustrates how to use Managed Code to:

  • Pass a .NET String into Managed C++
  • Manipulate a .NET String in Managed C++
  • Return a .NET String from Managed C++
  • Pass in arbitrary number of args into Managed C++

Remember to use a Class Library Project for Sample.h and Sample.cpp to create a Managed C++ Wrapper around native code API, and you can use the resulting Managed Assembly from Sample.cs managed code.




#pragma once
#include <windows.h>
#include "SomeNativeAPI.h"

using namespace System;
using namespace System::Runtime::InteropServices;

namespace Sample
    public ref class ManagedClass
        ManagedClass( String^ name );
        String^ DebugPrint( String^ format, ...array<String^>^ args );
        SomeNativeType* m_pType;


#include "Sample.h"

Sample::ManagedClass::ManagedClass( String^ name )
    // Convert .NET String into LPSTR for 
    // Native code API to use in constructor
    IntPtr szName;
    szName = Marshal::StringToHGlobalAnsi( name );
    m_pType = new SomeNativeType( szName );
    Marshal::FreeHGlobal( szName );
    delete m_pType;
String^ Sample::ManagedClass::DebugPrint( String^ format, ...array<String^>^ args )
    // Use Managed Code to format variable arguments as .NET String,
    // convert the .NET String into Unicode String, and pass
    // it to Native API
    String^ formattedString = System::String::Format( format, args );
    IntPtr  wszFormattedString;

    wszFormattedString = Marshal::StringToHGlobalUni( formattedString );
    m_pType->SomeFunctionUnicode( wszFormattedString );
    Marshal::FreeHGlobal( wszFormattedString );

    return formattedString;


namespace Sample
    class Program
        static void Main( string[] args )
            Sample.ManagedClass cls = new Sample.ManagedClass( "Name?" );
            System.Console.WriteLine( cls.DebugPrint( "0:{0},1:{1}", "N", "V" ) );