2010-04-14 18 views
10

Mam niezarządzanego dll z klasy "MyClass" w nim. Czy istnieje sposób utworzenia wystąpienia tej klasy w kodzie C#? Aby zadzwonić do swojego konstruktora? Próbowałem, ale studio graficzne zgłasza błąd z komunikatem, że ten obszar pamięci jest uszkodzony lub coś podobnego.Utwórz niezarządzanego obiektu C++ w c ​​#

Dzięki z góry

+0

Czy możesz opublikować, co próbujesz? – SwDevMan81

+0

i komunikat o błędzie? – Asher

+0

1) void główne (string [] arg) { IntPtr p = nowy IntPtr(); Program.CreateObserv (ref p); } [DllImport (@ "C: \ mm_2008 \ liba.dll" EntryPoint = "?? 0CRls @ FLD @@ QAE @ ABV01 @@ Z", SetLastError = prawda CallingConvention = CallingConvention.ThisCall)] wewnętrzny statyczny zewnętrzny nieważne CreateObserv (ref IntPtr s); kod ten zgłasza wyjątek AccessViolationException: accessviolationexception próbował odczytać lub zapisać chronioną pamięć ... – Evgeny007

Odpowiedz

19

C# nie można utworzyć instancję klasy wyeksportowany z natywną DLL. Dostępne są dwie opcje:

  1. Utwórz opakowanie C++/CLI. To jest biblioteka klasy .NET, którą można dodać jako odniesienie do dowolnego innego projektu .NET. Wewnętrznie klasa C++/CLI działa z klasą niezarządzaną, łącząc się z natywną biblioteką Dll według standardowych reguł C++. Dla klienta .NET ta klasa C++/CLI wygląda na klasę .NET.

  2. Zapis C otoki dla klasy C++, który może być używany przez klienta .NET z PInvoke. Na przykład, ++ klasa nadmiernie uproszczonym C:

 

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

C otoki API dla tej klasy:

 

    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 i GetData mogą być zadeklarowane w C# klienta przy użyciu PInvoke i nazwał bezpośrednio . void * Parametr powinien zostać zadeklarowany jako IntPtr w deklaracji PInvoke.

+1

Tęsknisz za zewnętrznym "C" w funkcjach opakowania. – Danvil

+0

Danvil - tak napisałem w notatce. W każdym razie, dzięki, teraz czuję się lepiej. –

+0

@Alex Co jeśli istnieje hierarchia klas w natywnej bibliotece C++ ... ?? – rsjethani

2

Nie można używać niezmienionego kodu C++ bezpośrednio w języku C#. Interoperacyjność można wykonać za pomocą PInvoke. Istnieje a lot of issues related to this topic, zwłaszcza podczas wywoływania funkcji, które mają wskaźniki jako argumenty.

Podstawowa procedura wygląda tak:

C# część

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

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

C++ część

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

MyClass* staticObject; 

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

podziękowania dla wszystkich, nienawidziłem tego przyznać, ale wygląda na to, nie ma innego wyjścia oprócz pisania otoki. – Evgeny007

+0

Inną opcją jest napisanie zarządzanego C++ za pomocą flagi kompilatora/pliku crl. Następnie możesz wymieszać kod niezarządzany i zarządzany w tej samej bibliotece dll, a następnie proste metody zarządzania połączeniami w kodzie C#. Spowoduje to utworzenie kodu sam IL, tak jak otoczyłbyś natywne metody w swoim kodzie. Szybkie wprowadzenie http://www.codeproject.com/Articles/19354/Quick-C-CLI-Learn-C-CLI-in-less-than-minutes –

2

Rozwiązaniem jest stworzenie C++/CLI otoki jak:

#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; 
    } 
}; 

gdzie CDllExportClass jest klasą wyeksportowaną z natywnego kodu. Powyżej jest .h C++/CLI. Uważaj, aby znaleźć lib do tej biblioteki. Umieść bibliotekę dll i bibliotekę w tym samym katalogu i skompiluj kod C++/CLI. W zarządzanym katalogu kodów umieść bibliotekę dll natywną i bibliotekę C++/CLI. W zarządzanym projekcie umieść odwołanie do projektu C++/CLI. Stanu w magedu kod klasy C++/CLI:

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

To wszystko.