Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: C++/CLI mit .NET ::  System::String and unmanaged Function aus c++ Dll übergeben [Gelöst]     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
_Sascha_
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2009
Beiträge: 74
Beitrag _Sascha_ Mitglied 14:25:06 03.05.2012   Titel:   System::String and unmanaged Function aus c++ Dll übergeben [Gelöst]            Zitieren

Hallo Zusammen...

resultierend aus diesem Thread möchte ich mit C++/CLI einen Wrapper Basteln, der mir eine Klasse aus einer C++ unmanaged Dll in C# zugänglich macht.

Die erstellte CLI dll gibt mir meine Klasse schon wunderbar an C# weiter jedoch gibt es bei den Methodenaufrufen noch ein Problem.

Die Launch() Methode funktioniert, da gibt es keine Probleme was jedoch nicht funktioniert ist die übergabe eines char*/wchar* pointers aus der ShowMessage Methodean an die unmanaged dll...hier bekomme ich eine Access Violation...

Ich habe schon diverse Methoden ausprobiert wie ich den System::String für unmanaged umformen kann...

z.B. wie hier beschrieben oder hier (um mal nur zwei Quellen zu nennen)

Die Zielmethode treibt keine komischen Sachen mit dem String, ich denke also, irgend etwas mache ich noch beim umformen/übergeben falsch..

Vorab, ich habe vorher noch nie etwas mit CLI gemacht von daher habt etwas Nachsehen mit mir :)

Hier der code:

C++/CLI:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public interface TestClassUnmanaged
{
    virtual int GimmeTheValue();
    virtual void ShowMessage(const wchar_t* msg);
};
 
public ref class wrapper
{
private:
    TestClassUnmanaged* m_pVal;
public:
    wrapper()
    {
        m_pVal = GetFunc();
    }
 
    [DllImportAttribute("c:\\asd.dll", EntryPoint = "?GetClass@@YAPAVTestClass@@XZ")]
    static TestClassUnmanaged* GetFunc ();
 
    Int32 Launch()
    {
        return m_pVal->GimmeTheValue();
    }
 
    void ShowMessage(String^ s)
    {
        std::wstring us2 = marshal_as<std::wstring>(s);
        m_pVal->ShowMessage(us2.c_str());
    }
};



Die TestKlasse in der unmanaged Dll sieht übrigens so aus
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TestClass
{
public:
    int m_nValue;
    TestClass(){m_nValue = 42;}
    virtual int GimmeTheValue(){return m_nValue;}
    virtual void ShowMessage(const wchar_t* msg)
    {
        MessageBox(NULL,msg,L"test Box",MB_OK);
    }
};
 
 
__declspec(dllexport) TestClass* __cdecl GetClass()
{
    return new TestClass();
}



Habt ihr einen Tipp für mich was ich da falsch mache?

Gruß
_Sascha_


Zuletzt bearbeitet von _Sascha_ am 10:30:28 04.05.2012, insgesamt 1-mal bearbeitet
theta
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.09.2008
Beiträge: 4074
Beitrag theta Mitglied 15:38:58 03.05.2012   Titel:              Zitieren

In C++/CLI musst Du eben NICHT P/Invoke (=DllImport) benutzen, sondern die DLL direkt (=wie bei einem "normalen" C++ Projekt) einbinden (=Headers zur Kompilierzeit, Import Library zur Linkzeit und DLL zur Laufzeit).

Edit:
Ausserdem sollten new / delete in derselben DLL stattfinden.


Zuletzt bearbeitet von theta am 15:42:27 03.05.2012, insgesamt 1-mal bearbeitet
_Sascha_
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2009
Beiträge: 74
Beitrag _Sascha_ Mitglied 17:01:57 03.05.2012   Titel:              Zitieren

LoadLibrary zur Laufzeit habe ich versucht...

Ich hatte etwas herum expereimentiert und das CLI Projekt zuerst als exe erstellt...da hat das mit dem LoadLibrary geklappt aber als ich eine Dll daraus gemacht habe und die Klasse mit ref gekennzeichnet habe, sodass ich sie in C# benutzen kann, ist das LoadLibray fehl geschlagen...


Zuletzt bearbeitet von _Sascha_ am 17:06:18 03.05.2012, insgesamt 2-mal bearbeitet
theta
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.09.2008
Beiträge: 4074
Beitrag theta Mitglied 18:15:52 03.05.2012   Titel:              Zitieren

Ich meine nicht LoadLibrary(..) sondern einfach *.lib angeben beim Linken. Das Programm lädt dann automatisch die DLL.
_Sascha_
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2009
Beiträge: 74
Beitrag _Sascha_ Mitglied 18:43:09 03.05.2012   Titel:              Zitieren

Ich verstehe nicht so recht... :confused:

das hier ist nur ein Testbeispiel...die eigentliche Dll die ich wrappen möchte liegt nur als Dll vor, nicht als lib...

sprich...die asd.dll bekomme ich zugeliefert...ich habe nur eine Beschreibung des Interfaces und die Dll


Zuletzt bearbeitet von _Sascha_ am 18:44:47 03.05.2012, insgesamt 1-mal bearbeitet
theta
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.09.2008
Beiträge: 4074
Beitrag theta Mitglied 23:02:01 03.05.2012   Titel:              Zitieren

Ok. Dann ist LoadLibrary(..) / GetProcAddress(..) angesagt.
Mische nicht P/Invoke (GetFunc) und "normale" Aufrufe (m_pVal->GimmeTheValue()).

Entscheide dich - entweder C Interface für die DLL oder C++ Interface (Klasse mit nur pure virt. Funktionen).

Edit:
Hier mal ein kleines Bsp. welches ev. dein Problem löst:

C++ DLL Code
Lib.hpp
C++:
1
2
3
4
5
6
7
8
9
10
11
#pragma once
 
class Lib
{
public:
    virtual void display(const wchar_t* message) = 0;
    virtual void destroy() = 0;
 
protected:
    ~Lib() {};
};


LibImpl.hpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once

#include "Lib.hpp"

 
extern "C"
{
    __declspec(dllexport) Lib* CreateLib();
}
 
class LibImpl
    : public Lib
{
public:
    // Lib interface
    virtual void display(const wchar_t* message);
    virtual void destroy();
};


LibImpl.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "LibImpl.hpp"

#include <iostream>

 
Lib* CreateLib()
{
    return new LibImpl();
}
 
void LibImpl::display(const wchar_t* message)
{
    std::wcout << message << std::endl;
}
 
void LibImpl::destroy()
{
    delete this;
}


C++/CLI Applikations Code
LibWrapper.h
C++/CLI:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma once

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
 
using namespace System;
 
class Lib;
 
ref class LibWrapperException
    : public Exception
{
};
 
ref class LibWrapper
{
public:
    LibWrapper();
    ~LibWrapper();
 
    void display(String^ message);
 
private:
    HMODULE module_;
    Lib* lib_;
};


LibWrapper.cpp
C++/CLI:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "stdafx.h"
#include "LibWrapper.h"

#include <Lib.hpp>


#include <string>

#include <msclr/marshal.h>
#include <msclr/marshal_cppstd.h>
 
LibWrapper::LibWrapper()
{
    module_ = LoadLibrary(L"Lib.dll");
 
    if (!module_)
    {
        throw gcnew LibWrapperException();
    }
 
    typedef Lib* (*CreateLib)();
    CreateLib func = reinterpret_cast<CreateLib>(GetProcAddress(module_, "CreateLib"));
    if (!func)
    {
        FreeLibrary(module_);
        throw gcnew LibWrapperException();
    }
 
    lib_ = func();
}
 
LibWrapper::~LibWrapper()
{
    lib_->destroy();
    FreeLibrary(module_);
}
 
void LibWrapper::display(String^ message)
{
    std::wstring s = msclr::interop::marshal_as<std::wstring>(message);
    lib_->display(s.c_str());
}


Main.cpp
C++/CLI:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "stdafx.h"
#include "LibWrapper.h"
 
using namespace System;
 
int main(array<System::String ^> ^args)
{
    LibWrapper wrapper;
 
    wrapper.display(L"Test");
 
    return 0;
}


Bemerkung: Ich wusste grad nicht wie man in C++/CLI eine Klasse Non-Copyable macht - man sollte aber.

Unterschiede zu deinem Code:
- Benutzung von LoadLibrary(..) / GetProcAddress(..) anstelle von DllImport
- Export der Factory Methode als extern "C" was das Namemangeling ausschaltet
- Löschen der Lib Instanz in der Lib DLL durch Lib::destroy()
- Bei meinem Code haben Interface und Implementation was miteinander zu tun, bei dir nicht (TestClassUnmanaged und TestClass) - zudem ist bei Dir das Interface managed (?), die Implementation aber nicht.


Zuletzt bearbeitet von theta am 23:44:47 03.05.2012, insgesamt 1-mal bearbeitet
_Sascha_
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2009
Beiträge: 74
Beitrag _Sascha_ Mitglied 09:50:26 04.05.2012   Titel:              Zitieren

Hi,

danke für dein Ausführliches Beispiel. Echt klasse!
Ich werde es mir nachher gleich mal zu Gemüte führen und mein Testprojekt anpassen.

Zitat:
Bemerkung: Ich wusste grad nicht wie man in C++/CLI eine Klasse Non-Copyable macht - man sollte aber.
Ich würde es wie bei normalem c++ gemacht...Operator= und Copy-Constructor private machen...aber wenn es da ein Schlüsselwort dafür gibt würde mich das auch interessieren :)

Gruß
_Sascha_


Zuletzt bearbeitet von _Sascha_ am 10:39:04 04.05.2012, insgesamt 1-mal bearbeitet
_Sascha_
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.05.2009
Beiträge: 74
Beitrag _Sascha_ Mitglied 10:29:00 04.05.2012   Titel:              Zitieren

Hi...
funktioniert jetzt prima...auch die char* Übergabe :)

:arrow: Jetzt werde ich das mal auf die eigentliche Dll übertragen die ich wrappen möchte, falls ich da nochmal fragen habe, werde ich mich vertrauensvoll an dich wenden :)

Also Danke nochmal. :live:

Gruß
_Sascha_
c++.de :: C++/CLI mit .NET ::  System::String and unmanaged Function aus c++ Dll übergeben [Gelöst]   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.