2010-04-14 5 views
10

Ich habe eine nicht verwaltete DLL mit einer Klasse "MyClass" drin. Jetzt gibt es eine Möglichkeit, eine Instanz dieser Klasse in C# -Code zu erstellen? Um seinen Konstruktor aufzurufen? Ich habe versucht, aber das Visual Studio meldet einen Fehler mit einer Nachricht, dass dieser Speicherbereich beschädigt ist oder so etwas.Erstellen Sie nicht verwalteten C++ - Objekt in C#

Vielen Dank im Voraus

+0

Können Sie posten, was Sie versucht haben? – SwDevMan81

+0

und die Fehlermeldung? – Asher

+0

1) static void Haupt (string [] args) { IntPtr p = neue IntPtr(); Program.CreateObserv (ref p); } [DllImport (@ "C: \ mm_2008 \ liba.dll" Entrypoint = "?? 0CRls @ @@ FLD QAE @ @@ ABV01 Z", SetLastError = true, Calling = Calling.ThisCall)] intern statisch extern void CreateObserv (ref IntPtr p); dieser Code löst eine Access: Access zu lesen versucht oder geschützten Speicher schreiben ... – Evgeny007

Antwort

19

C# nicht Klasseninstanz exportiert aus nativen DLL erstellen können. Sie haben zwei Optionen:

  1. Erstellen Sie C++/CLI-Wrapper. Dies ist die .NET-Klassenbibliothek, die als Referenz zu anderen .NET-Projekten hinzugefügt werden kann. Intern arbeitet die C++/CLI-Klasse mit der nicht verwalteten Klasse und verbindet sich über standardmäßige C++ - Regeln mit der nativen Dll. Für .NET-Clients sieht diese C++/CLI-Klasse wie eine .NET-Klasse aus.

  2. Schreiben C-Wrapper für C++ - Klasse, die von .NET-Client mit PInvoke verwendet werden kann. Zum Beispiel über vereinfachte C++ Klasse:

 

    class MyClass() 
    { 
    public: 
     MyClass(int n){data=n;} 
     ~MyClass(){} 
     int GetData(){return data;} 
    private: 
     int data; 
    }; 

C-API-Wrapper für diese Klasse:

 

    void* CreateInstance() 
    { 
     MyClass* p = new MyClass(); 
     return p; 
    } 

    void ReleaseInstance(void* pInstance) 
    { 
     MyClass* p = (MyClass*)pInstance; 
     delete p; 
    } 

    int GetData(void* pInstance) 
    { 
     MyClass* p = (MyClass*)pInstance; 
     return p->GetData(); 
    } 

    // Write wrapper function for every MyClass public method. 
    // First parameter of every wrapper function should be class instance. 

CreateInstance, ReleaseInstance und GetData kann direkt in C# Client mit PInvoke und rief deklariert werden . void * Parameter sollte als IntPtr in PInvoke Deklaration deklariert werden.

+1

Sie vermissen ein externes "C" in den Wrapper-Funktionen. – Danvil

+0

Danvil - das habe ich in den Fragezettel geschrieben. Wie auch immer, danke, ich fühle mich jetzt wirklich besser. –

+0

@Alex Was ist, wenn es eine Hierarchie von Klassen in der nativen C++ - DLL gibt ... ?? – rsjethani

2

Sie können nicht verwalteten C++ - Code nicht direkt in C# verwenden. Die Interoperabilität kann mit PInvoke erfolgen. Es gibt a lot of issues related to this topic, besonders wenn Funktionen aufgerufen werden, die Zeiger als Argumente haben.

Das grundlegende Verfahren geht so:

C# Teil

namespace MyNamespace { 
    public class Test { 
    [DllImport("TheNameOfThe.dll")] 
    public static extern void CreateMyClassInstance(); 

    public void CallIt() { 
     CreateMyClassInstance(); // calls the unmanged function via PInvoke 
    } 
    } 
} 

C++ Teil

class MyClass { 
    public: MyClass() { /** Constructor */ } 
}; 

MyClass* staticObject; 

extern "C" void CreateMyObjectInstance() { 
    staticObject = new MyClass(); // constructor is called 
} 
+0

danke an alle, ich hasste es zugeben, aber es sieht so aus, als gäbe es keinen anderen Weg als einen Wrapper zu schreiben. – Evgeny007

+0

Andere Option ist, verwaltetes C++ mit Compiler/CRL-Flag zu schreiben. Dann können Sie nicht verwalteten und verwalteten Code in derselben DLL mischen und dann einfach in Ihrem C# -Code verwaltete Methoden aufrufen. Es erzeugt Sam-IL-Code, wie Sie native Methoden in Ihren Code einfügen würden. Schnelle Einführung http://www.codeproject.com/Articles/19354/Quick-C-CLI-Learn-C-CLI-in-less-than-minutes –

2

Die Lösung ist erstellen C++/CLI-Wrapper wie:

#include "DllExportClass.h" 

public ref class ManagedOperationHelper 
{ 
    public: 

    double Sum(double add1, double add2) 
    { 
     CDllExportClass obj; 
     double ret=obj.Sum(add1, add2); 
     return ret; 
    } 

    double Mult(double mult1, double mult2) 
    { 
     CDllExportClass obj; 
     double ret=obj.Mult(mult1, mult2); 
     return ret; 
    } 
}; 

Dabei ist CDllExportClass die aus dem systemeigenen Code exportierte Klasse. Oben ist das .h von C++/CLI. Achten Sie darauf, die lib zu dieser DLL zu finden. Setzen Sie die DLL und die Lib in das gleiche Verzeichnis und kompilieren Sie den C++/CLI-Code. Im verwalteten Code-Verzeichnis setzen Sie die native DLL und die C++/CLI-DLL. Fügen Sie im verwalteten Projekt die Referenz des C++/CLI-Projekts ein. Im C++/CLI-Code wird die C++/CLI-Klasse wie folgt initialisiert:

ManagedOperationHelper obj = new ManagedOperationHelper(); 
double ret=obj.Sum(10, 20); 

Es ist alles.

Verwandte Themen