Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++/C#] Managed objecten gebruiken in unmanaged programma

Pagina: 1
Acties:

  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11 13:20
Ik heb een programma dat werkt met onder andere scripts en COM-objecten.
Elke "module" implementeerd IDispatch, en communiceert met een aantal andere IDispatch interfaces.

Nu wil ik echter naast JScript en COM ook graag .NET talen als mogelijkheid hebben om modules te schrijven, dus ik ben op zoek naar een methode om een .NET dll te schrijven waaruit ik een IDispatch kan ontvangen, en die op zijn beurt ontvangen IDispatch's kan gebruiken.


Vanuit .NET IDispatch gebruiken lijkt vrij simpel door het gebruik van het "object" type en dan obj.GetType().InvokeMember te gebruiken.

Echter, om vanuit mijn C++ code een .NET class als COM object aanroepen lukt me niet :(
Wat ik tot nu toe heb is:
ICorRuntimeHost aanmaken met CorBindToRuntimeEx (lijkt te werken)
ICorRuntimeHost->Start (lijkt te werken)
ICorRuntimeHost->GetDefaultDomain + QueryInterface naar _AppDomain (geeft geen foutmeldingen).
_AppDomain->CreateInstanceFrom("DotNetTest.dll","DotNetTest.Class1"), geeft foutcode 0x80070002. (werkt ook)
Echter, als ik dan GetIDsFromNames probeer aan te roepen, krijg ik alleen DISPID_UNKNOWN :(

Ik heb al heel heel erg veel gezocht, en ik zie echt niet meer hoe het anders moet. Code zoals ik hierboven heb zie ik overal, alleen nergens met concrete voorbeelden van de .NET kant.

Wat ik tot nu toe als .NET kant aangehouden heb is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace DotNetTest
{
    public class Class1
    {
        public void RegisterObject(string name, object obj)
        {
            if (name == "Console")
            {
                object[] args=new object [1];
                args[0]="Test 1 2 3";
                obj.GetType().InvokeMember("Error",BindingFlags.InvokeMethod,null,obj,args);
            }
        }
    }
}


Heeft iemand hier enige ervaring mee die me op weg kan helpen?
Ik zoek me nu al ruim 3 uur suf op google, en kom echt niet verder. Zelfs de MSDN documentatie is uitermate vaag over dit onderwerp :(

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Ik neem aan dat je wel voorbeelden gevonden hebt met google?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11 13:20
pedorus schreef op maandag 18 februari 2008 @ 09:45:
Ik neem aan dat je wel voorbeelden gevonden hebt met google?
Die methoden heb ik inderdaad gezien, maar hiervoor moet je specifiek definieren hoe je interface eruitziet en registreren. Het is voor mijn doel handiger om gewoon vanuit een ongeregistreerde DLL te werken, en zonder alle methoden van het object te weten, vandaar als IDispatch.

Overigens heb ik alles nu werkend, het bleken veelal typos die men nog wel eens maakt om 3 uur 's nachts 8)7

Het enige waar ik nu nog mee zit is hoe ik .NET wat makkelijker naar een IDispatch kan laten roepen.
op zich werkt dit wel:
obj.GetType().InvokeMember("Log", BindingFlags.InvokeMethod, null, obj, new object[1] { "Oude stijl" });
Maar dat is toch vrij lelijk :(

Wat wel werkt is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
[ComImport()]
    [Guid("C952DD6B-F028-471B-943D-3F4E8A2D7908")] 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    public interface ConsoleModule
    {
        void Show();
        void Hide();
        void Log([Out, MarshalAs(UnmanagedType.BStr)] string str);
        void Information([Out, MarshalAs(UnmanagedType.BStr)] string str);
        void Warning([Out, MarshalAs(UnmanagedType.BStr)] string str);
        void Error([Out, MarshalAs(UnmanagedType.BStr)] string str);
    }

Echter moet ik dan perse een GUID meegeven (die ook gechecked wordt), en sommige objecten zijn ook gewoon pure IDispatches zonder bovenliggende interface...
Bovenstaande code werkt wel (dus van obj casten naar ConsoleModule), maar zodra ik ComImport weghaal niet meer.
Als ik Guid weghaal, dan wil hij niet compilen met ComImport.

Weet iemand hoe ik dit wel goed aanpak? dus een IDispatch interface kan definieren als echt puur en alleen IDispatch ?

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Misschien dat het gewoon kan in .Net op de manier zoals je nu bezig bent, dus ik wil niet beweren dat het volgende het beste advies is, maar je zou kunnen overwegen om het marshallen in C++ te implementeren. Oftewel, maak een functie in C++ die gegeven een handle naar een Com object een .Net interface teruggeeft. Vanuit .Net kun je dan gewoon die C++ functie aanroepen, zodat je een interface terugkrijgt waar je wel fatsoenlijk mee kunt werken.

[ Voor 4% gewijzigd door .oisyn op 18-02-2008 17:10 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11 13:20
.oisyn schreef op maandag 18 februari 2008 @ 17:10:
Misschien dat het gewoon kan in .Net op de manier zoals je nu bezig bent, dus ik wil niet beweren dat het volgende het beste advies is, maar je zou kunnen overwegen om het marshallen in C++ te implementeren. Oftewel, maak een functie in C++ die gegeven een handle naar een Com object een .Net interface teruggeeft. Vanuit .Net kun je dan gewoon die C++ functie aanroepen, zodat je een interface terugkrijgt waar je wel fatsoenlijk mee kunt werken.
Volgens mij zou dat niet echt opgaan in mijn situatie. Immers wil ik het hoofd programma zo generiek mogelijk houden, afgezien van een paar functies die die aanroept in de modules om alles te coordineren, zijn de modules verder vrij in wat voor extra functies ze definieren.

Als Module A een functie heeft Log, dan moet module B daar gebruik van kunnen maken zonder medeweten van het hoofdprogramma. Dit kan al voor de GetType().InvokeMethod methode, maar dit is erg lelijk, en als je tijdens het schrijven van module B toch al weet dat module A de functie Log heeft, waarom is het dan niet mogelijk om een soort interface te genereren waarnaar ik kan casten?
Omdat module A ook best een JScript object kan zijn (waar dus geen typelib van is, geen vtbl heeft, en echt alleen IDispatch is), *moet* (voor zover ik heb gelezen) alles dus via late-binding en via System.Reflection. Is er dan geen manier in Reflection om een method vantevoren te definieren in plaats van InvokeMethod?

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah ok, nee dan is dat idd niet handig.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1