Interop Fundamentals in .NET

10/01/2024

Introduction

Execution Modes

Managed execution

Unmananged execution

Managed vs Native Code

Managed (.NET) Native Programming Languages
Code execution Safety ensured by the CLR No safety guarantees
Memory management Garbage collection manual
Error handling execption handling return values / SEH / C++ exceptions

Interoperability Scenarios

Interoperability Mechanisms

P/Invoke: The Basics

Finding Entry Points

Calling Convention

Type Conversion

void _stdcall DoWork(LPCWSTR s1, LPCSTR s2, LPCTSTR s3, BSTR s4);

[DllImport("somelib")]
static extern void DoWork(
  [MarshalAs(UnmangedType.LPWStr)] string s1,
  [MarshalAs(UnmangedType.LPStr)] string s2,
  [MarshalAs(UnmangedType.LPTStr)] string s3,
  [MarshalAs(UnmangedType.BStr)] string s4,
);

P/Invoke: Digging Deeper

Error Handling

Structures and Unions

Function Pointers

Object Lifetime

Guidelines

COM Interop: Foundations

The Component Object Model (COM)

COM Object

GUIDs

HRESULTs

Common HRESULTs

HRESULT Meaning
S_OK standard success code (=0)
S_FALSE partial success in some sense (=1)
E_FAIL generic failure code
E_POINTER bad pointer supplied
E_UNEXPECTED unexpected call at this time
E_NOINTERFACE the requested interface is not supported
E_NOTIMPL functionality not implemented
E_OUTOFMEMORY not enough memory to complete the operation
E_INVALIDARG argument is invalid

Activation APIs

COM Registration

Typical DOM DLL

Basic COM Interop

Summary

COM Interop: Digging Deeper

IUnknown in .NET

ISimpleCalculator calc = new Calculator();
int sum = calc.Add(3, 4);

ITrigCalculator trig = calc as ITrigCalculator;
if (trig != null) {
  double result = trig.Sin(30);
  // use result
}

Memory Management

Interop with no Type Library

Dynamic Dispatch

interface IDispatch : IUnkown {
  // ...
  HRESULT _stdcall GetIDsOfNames(...);
  HRESULT _stdcall Invoke(...);
}

Exposing .NET types as COM types

Summary

COM Interop: Threading

Processses and Threads

Process

Thread

COM and Threading

Threads and Apartments

Objects and Apartments

Setting Apartment Type Notes
Single Main STA first STA in process (legacy setting)
Apartment STA
Free MTA
Both STA or MTA in the calling thread's apartment
Neutral TNA

Apartments and the CLR

"Both" and FTM

Summary

Interop With C++/CLI

What is C++/CLI?

C++/CLI Usage Scenarios

C++/CLI Basics

Hello World - C++/CLI Demo

Declaration Syntax

.NET Class (reference type)

ref class Book { /* */ };

.NET Struct (value type)

value class Point { /* */ };

.NET interface

interface class ILearn { /* */ };

.NET enum

enum class Gender { /* */ };

Properties, Methods, and Events

public ref class Book {
public:
  Book(String^ path);
  
  String^ ReadPage(int pageNumber);
  void GoToNextPage();

  property int length {
    int get();
  }

  event EventHandler^ PageTurned;
};

Objects and References

Demo

#include "stdafx.h"

using namespace System;
using namespace System::Linq;

int main(array<System::String ^> ^args)
{
  Console::WriteLine(L"Hello Word");

  auto rnd = gcnew Random;
  Console::WriteLine(rnd->Next(1, 100));

  array<int>^ numbers = gcnew array<int>(100);
  for (int i = 0; i < numbers->Length; i++)
    numbers[i] = rnd->Next(0, 100);
  
  int sum = Enumerable::Sum(numbers);
  int average = Enumerable::Average(numbers);

  Console::WriteLine(sum);
  Console::WriteLine(average);

  {
    System::ID::MemoryStream ms(100);
    auto len = ms.Length;
  }

  return 0;
}

Exposing Native Types to .NET

Summary

Tips and Tidbits

Unsafe Code

Normal C# is safe

Unmanaged Code (Native Code)

Unsafe Code

The Unsafe Keyword

Bitness

Properties in COM

[propget] HRESULT Degrees([out, retval] VARIANT_BOOL* pVal);
[propget] HRESULT Degrees([in] VARIANT_BOOL newVal);

COM Events

coclass RPN Calculator {
  [default] interface IRPNCalculator;
  [default, source] dispinterface _IRPNCalculatorEvents;
}

Summary

© 2024 by Ryan Rickgauer