Toon posts:

[C++/CLI] Runtime laden van dlls

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik, met collega, ben op dit moment bezig programma waarbij we gebruik willen maken van plugins. Het is de bedoeling dat het programma één hoofddeel krijgt en daarnaast gebruik kan maken van plugins die gekozen kunnen worden door de gebruiker. Deze plugins worden ook door ons zelf geschreven en gecompileerd tot dll.
Het programma wordt geschreven in (visual) C++ en gecompileerd met Microsoft Visual Express 2005. Wij hebben ervoor gekozen om alle klasse “managed” te maken.

Het probleem is nu om de dlls runtime te laden.
Na zoeken via google en msdn ben ik twee dingen tegengekomen:
1. Gebruik maken van GetProcAddress() / DllMain http://msdn.microsoft.com/library/...
2. Gebruik maken van DllImporthttp://msdn.microsoft.com/library/...

De eerste optie heeft als nadeel dat deze niet managed is.
De tweede optie heeft als nadeel dat het buiten klasse en functies om moet. Hierbij wordt het moeilijk om parameters mee te geven, b.v. welke dll er geladen moet worden.

Ik vraag me nu af of het mogelijk is dat er runtime gekozen kan worden welke dlls er geladen moeten worden?

[ Voor 6% gewijzigd door Verwijderd op 03-10-2006 20:38 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 11:29
Nu, allereerst, ik heb geen ervaring met C++/CLI, maar wel met het dynamisch laden van dll's in C#.
In .NET heb je 'reflection', en daarmee kan je assemblies dynamisch laden.

Bv:
C#:
1
2
3
4
5
6
7
8
9
10
11
Assembly asm = Assembly.LoadFrom ("bliep.dll");
if( asm == null )
{
   throw new ApplicationException ("not found.");
}
object o = asm.CreateInstance ("namespace.typename");
IPluginInterface plugin = o as IPluginInterface;
if( plugin == null )
{
   throw new ApplicationException ( ... );
}

Dit moet ook wel mogelijk zijn in C++/CLI denk ik.

https://fgheysels.github.io/


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

het kan ook op een iets robuustere manier door aan de Assembly alle Type's op te vragen die een gegeven interface implementeren. Heb je ook minder kans op Exceptions etc.

Ik kan je nog een handige tip meegeven. Probeer om DLL's een vaste prefix of iets dergelijk te geven. Een geladen DLL kan je in .NET niet meer vrijgeven (in C++ kan dit wel). Probeer dus op die manier enkel de DLL's te laden die je nodig hebt (tenzij je ze in een config bestand of zo zet)

ASSUME makes an ASS out of U and ME


  • Korben
  • Registratie: Januari 2001
  • Laatst online: 14-11-2025

Korben

() => {};

HIGHGuY schreef op woensdag 04 oktober 2006 @ 18:40:
het kan ook op een iets robuustere manier door aan de Assembly alle Type's op te vragen die een gegeven interface implementeren. Heb je ook minder kans op Exceptions etc.

Ik kan je nog een handige tip meegeven. Probeer om DLL's een vaste prefix of iets dergelijk te geven. Een geladen DLL kan je in .NET niet meer vrijgeven (in C++ kan dit wel). Probeer dus op die manier enkel de DLL's te laden die je nodig hebt (tenzij je ze in een config bestand of zo zet)
Wel als je die assembly laadt in een apart AppDomain. Dan kun je simpelweg dat hele AppDomain unloaden en is die geladen assembly ook weg.

Overigens aan de TS, voor zover ik weet heb je bij een managed DLL vrij weinig aan GetProcAddress en al helemaal niet aan DllMain. Een managed DLL exporteert namelijk helemaal geen functies waar GetProcAddress wat mee kan.

[ Voor 13% gewijzigd door Korben op 05-10-2006 02:14 ]

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


  • __fred__
  • Registratie: November 2001
  • Laatst online: 11-02 07:23
Whoami geeft het juiste antwoord, alleen even omschrijven naar C++/cli.
Overigens is een heel mooie manier om dit af te handelen via inversion of control / dependency injection.

http://www.martinfowler.com/articles/injection.html
http://en.wikipedia.org/wiki/Inversion_of_Control

In het wikipedia artikel staan wat referenties naar .NET implementaties. Overigens is object builder uit het Enterprise framework van microsoft ook een aardige implementatie.

Ow, ik zie net dat die er al tussenstond O+

[ Voor 4% gewijzigd door __fred__ op 05-10-2006 14:58 ]


Verwijderd

Topicstarter
Ik heb op dit moment een werkende oplossing gemaakt met het voorbeeld van whoami en msdn. Bedankt voor het voorbeeld :).

code:
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
using namespace System::Reflection;
Assembly^ assem = Assembly::LoadFrom(s);
if(assem == nullptr)
{
    // File is geen assembly
}
else
{
    // Dll is geladen
    AssemblyName^ assemName = assem->GetName();
    String^ pluginnaam = assemName->Name;

    Object^ o = assem->CreateInstance("namespace_" + pluginnaam + "." + pluginnaam, false);
    if(o == nullptr)
    {
        // Constructor kan niet worden aangeroepen
    }
    else
    {           
        // Assembly naar een Plugin casten 
        Plugin^ plugin = dynamic_cast<Plugin^>(o);
        if(plugin == nullptr)
        {
            // Mislukt, onmogelijke cast
        }
        else
        {
            // Gelukt
        }
    }
}


De namespace is een beetje ransig geworden, maar wordt nu afgeleid uit de dll naam.

Ik ga nog even de links van __fred__ doorkijken naar het inversion of control en dependency injection.
Danke voor de tips.

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Korben schreef op donderdag 05 oktober 2006 @ 02:10:
[...]

Wel als je die assembly laadt in een apart AppDomain. Dan kun je simpelweg dat hele AppDomain unloaden en is die geladen assembly ook weg.
juist ja... was ik even vergeten... maar dat is imo nog steeds met een bazooka op een mug knallen...

ASSUME makes an ASS out of U and ME

Pagina: 1