Main /

Unmanaged Code Aus Dot Net Aufrufen

Unmanaged Code Aus Dot Net Aufrufen

Aufrufen von unmanaged C++ Code aus einem C#-Programm mit Visual Studio 2010

Mit dieser Step-By-Step Anleitung wird gezeigt wie man ein C# Array mit unmanaged C++ beschreiben kann. Dazu wird eine c++-dll erzeugt und diese in C#-Code eingebunden.

1. C++-DLL-Projekt anlegen

In Visual Studio 2010 ein neues Projekt anlegen: Visual C++ -> Win32 -> Win32 Project. Wir nennen es "UnmanagedDllTest". Dann die Application Settings auf "DLL" stellen. Ein Projekt wird erzeugt.

2. Generierten Code Entmüllen

Es können alle erzeugten Ordner und Dateien mit Ausnahme von dllmain.cpp gelöscht werden

3. Funktion schreiben

Man definiert eine Funktion die in diesem Beispiel FillArray heißt. Sie beschreibt die ersten zehn Werte eines ushort[] Arrays mit aufsteigenden Zahlen. Der Nachfolgende Code ist der komplette Inhalt von dllmain.cpp.

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
   return TRUE;
}

extern "C" __declspec(dllexport) void __stdcall FillArray(unsigned short* p_array)
{
   for (unsigned short i=0; i<=10; i++)
   {
      *p_array++ = i;
   }
}

Wichtig ist hierbei das extern "C", wenn dieses fehlt kann die DLL nur mit hilfe eines manged C++ Wrappers in .NET verwendet werden.

4. DLL builden

Die DLL (UnmanagedDllTest.dll) wird kompiliert und landet wie gewohnt im debug Subfolder des DLL-Projektes.

5. C#-Konsolenanwendung erzeugen

Ein neues Projekt anlegen: Visual C# -> Windows -> Console Application

6. C# Code schreiben

using System;
using System.Runtime.InteropServices;

class MainClass
{
    [DllImport("UnmanagedDllTest.dll")]
    static extern void FillArray(ushort[] p_array);

    public static void Main()
    {
        ushort[] arr = new ushort[11];

        try
        {
            Console.WriteLine("Before: ");
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine(arr[i]);
            }

            FillArray(arr);
            Console.WriteLine("After: ");
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine(arr[i]);
            }
        }
        catch (DllNotFoundException e)
        {
            Console.WriteLine(e.ToString());
        }
        catch (EntryPointNotFoundException e)
        {
            Console.WriteLine(e.ToString());
        }
    }
};

Nach kompilieren und starten gibt es zunächst eine Exception, denn die dll wurde nicht gefunden. Sie muss erst in den debug-Ordner des c#-Projektes kopiert werden.

Danach kann das Programm erneut gestartet werden und läuft:

7. Fazit

Interessanterweise muss man von C# keinen Pointer auf ein Array übergeben (was zweifelsohne möglich wäre) sondern das Array direkt. Intern wird bei komplexen Datentypen ein Pointer verwendet. Wie man andere, komplexere Datentypen (Objekte) von C++ aus anspricht habe ich noch nicht ausprobiert.

Der Aufruf aus C# scheint einen gewissen Overhead zu erzeugen, sodass es sich nur lohnt unmanaged c++ code zu verwenden wenn diese wirklich viel schneller ist. Augenscheinlich ist der JIT von .NET mittlerweile so gut dass es kaum Performancevorteile, ja sogar nachteile bringt. Meine Funktionen zur Helligkeits- und Kontrastveränderung von Bildern sind in C# mit Pointern jedenfalls schneller als eine äquivalente C++ Version.

Links

Frische Änderungen | Menü editieren
zuletzt geändert am 21.05.2010 01:52 Uhr von Elsni
Edit Page | Page History