none
C++/CLI - How to translate <Export(GetType(IPlugin))>?

    Question

  • Hey folks. I got a Plugin Host whicht expects a DLL that is TypeOf(iPlugin) Internface. This Host is written under VB.NET Framework 4.5.

    However: How do I write a Plugin under C++/CLI that is exporting that iPlugin::TypeId?

    I have to following but it will not be recognized by the catlog/container classes as type of iPlugin.

    How do I have to export the ID in a correct way? My definition in the header file is:

    #pragma once
    
    using namespace System;
    using namespace System::ComponentModel::Composition;
    using namespace SharedLibrary;
    using namespace Plugin_Interface;
    
    namespace MyCppPlugin {
    	
    	[System::ComponentModel::Composition::ExportAttribute(IPlugin::typeid)]
    	public ref class MyPlugin abstract : public Plugin_Interface::IPlugin
    	{
    	public:
    		virtual bool CreateInstance(SharedLibrary::MemoryArbiter^%, SharedLibrary::clsMessageQueue^%, SharedLibrary::clsGPIO^%, SharedLibrary::Types^%, SharedLibrary::DisplayDriver^%);
    		virtual bool DeleteInstance(void);
    		virtual void ForceUnload(void);
    		virtual void Interrupt(void);
    		virtual void Main_Loop(void);
    	};
    };

    Thank you :)

    Sunday, January 26, 2014 5:14 PM

Answers

  • Try the 64-bit version of C++ DLL. Use menu à BUILD à Configuration Manager. Then rebuild the solution.

    For checks, you can also try referencing this DLL directly from some VB.NET project; then try calling CreateInstance.

    • Marked as answer by Nils Thomsen Monday, January 27, 2014 8:08 PM
    Sunday, January 26, 2014 8:22 PM

All replies

  • Does it work if you remove “abstract”?

    Or try a simple plugin in VB.NET and see if it is visible in this case.


    • Edited by Viorel_MVP Sunday, January 26, 2014 6:16 PM
    Sunday, January 26, 2014 6:16 PM
  • No, removing the abstract doesn't change anything.

    Plugins written in VB.NET work perfectly. Hence I can export the iPlugin Type within an vb.net plugin, the plugin is recognized as it should.

    Class clsInterface
    
        <ImportMany(GetType(IPlugin))> _
        Public Plugins As IPlugin()
    
        Public Sub Load()
            Dim MyDialog As Windows.Forms.FolderBrowserDialog = New FolderBrowserDialog()
    
            MyDialog.Description = "Bitte Plugin-Verzeichnis auswählen"
            MyDialog.SelectedPath = Environment.CurrentDirectory
    
            MyDialog.ShowDialog()
    
            Dim catalog = New DirectoryCatalog(MyDialog.SelectedPath)
            Dim container = New CompositionContainer(catalog)
            container.ComposeParts(Me)
        End Sub
    
    End Class

    This is the Code of the Interface.vb. If I break at the catalog statement, i can see that it has found my CLI-Plugin, and I can see, that it is type of IPlugin. But its not recognized.

    <del>May this be caused by the different Framework Versions? The host is 4.0, the C++/CLI Plugin is 4.5?!</del>


    Sunday, January 26, 2014 6:22 PM
  • If both of host and plugin modules use the same version of .NET and also switching between 32- and 64-bit configurations of C++ module does not help, then show the VB.NET declarations of IPlugin and derived plugin that work. Maybe the code is not correctly translated to C++.

    Sunday, January 26, 2014 6:54 PM
  • Sure - here we go (it might be a little complex):

    SharedLibrary contains only some classes defining object structures.

    Interface.dll:

    Imports SharedLibrary
    
    Public Interface IPlugin
        Function CreateInstance( _
                ByRef pntMemory As MemoryArbiter, _
                ByRef pntMessageQueue As clsMessageQueue, _
                ByRef pntGPIO As clsGPIO, _
                ByRef pntProgramSettings As Types, _
                ByRef pntDisplayDriver As DisplayDriver _
            ) As Boolean
    
        Function DeleteInstance() As Boolean
    
        Sub Main_Loop()
        Sub ForceUnload()
        Sub Interrupt()
    End Interface
    

    VB.NET Plugin.dll:

    Imports System.ComponentModel.Composition
    Imports System.Windows.Forms.Application
    
    Imports Plugin_Interface
    Imports SharedLibrary
    Imports SharedLibrary.DisplayDriver
    
    <Export(GetType(IPlugin))>
    Public Class cPlugin
        Implements IPlugin
    
        Public Function CreateInstance(ByRef pntMemory As SharedLibrary.MemoryArbiter, _
                                            ByRef pntMessageQueue As SharedLibrary.clsMessageQueue, _
                                            ByRef pntGPIO As SharedLibrary.clsGPIO, _
                                            ByRef pntProgramSettings As SharedLibrary.Types, _
                                            ByRef pntDisplayDriver As SharedLibrary.DisplayDriver) _
                                       As Boolean Implements Plugin_Interface.IPlugin.CreateInstance
    
    
            '<some code>
    
            Return True
        End Function
    
        Public Sub Main_Loop() Implements Plugin_Interface.IPlugin.Main_Loop
            '<some code>
        End Sub
    
        Public Function DeleteInstance() As Boolean Implements Plugin_Interface.IPlugin.DeleteInstance
            Return True
        End Function
    
        Public Sub ForceUnload() Implements Plugin_Interface.IPlugin.ForceUnload
            '<some code>
        End Sub
    
        Public Sub Interrupt() Implements Plugin_Interface.IPlugin.Interrupt
            '<some code>
        End Sub
    
    End Class

    And the Plugin.dll in C++/CLI:

    //###################### HEADER ######################
    
    #pragma once
    
    using namespace System;
    using namespace System::ComponentModel::Composition;
    using namespace SharedLibrary;
    using namespace Plugin_Interface;
    
    namespace testnamespace {
    
    	//[System::ComponentModel::Composition::ExportAttribute(IPlugin::typeid)]
    	[Export(IPlugin::typeid)]
    	public ref class MyPlugin : public Plugin_Interface::IPlugin
    	{
    	public:
    		virtual bool CreateInstance(SharedLibrary::MemoryArbiter^%, SharedLibrary::clsMessageQueue^%, SharedLibrary::clsGPIO^%, SharedLibrary::Types^%, SharedLibrary::DisplayDriver^%);
    		virtual bool DeleteInstance(void);
    		virtual void ForceUnload(void);
    		virtual void Interrupt(void);
    		virtual void Main_Loop(void);
    	};
    };
    
    
    //######################  CPP  #######################
    
    
    #include "stdafx.h"
    #include "MyPlugin.h"
    
    
    bool testnamespace::MyPlugin::CreateInstance(SharedLibrary::MemoryArbiter^%, SharedLibrary::clsMessageQueue^%, SharedLibrary::clsGPIO^%, SharedLibrary::Types^%, SharedLibrary::DisplayDriver^%) {
    	
    	return(true);
    
    };
    
    bool testnamespace::MyPlugin::DeleteInstance()
    {
    	return(true);
    };
    
    void testnamespace::MyPlugin::ForceUnload(){};
    void testnamespace::MyPlugin::Interrupt(){};
    void testnamespace::MyPlugin::Main_Loop(){};

    Having a look into both Plugins with the .Net Reflector it seems like both Plugins do have the exactly same strcuture. But if it was like this, the host Application should be able to open the Plugin from C++/CLI as it does with the vb.NET Plugin.

    This is very strange and has cost me the whole day without even the tiniest bit of success :-(

    Sunday, January 26, 2014 7:32 PM
  • Try the 64-bit version of C++ DLL. Use menu à BUILD à Configuration Manager. Then rebuild the solution.

    For checks, you can also try referencing this DLL directly from some VB.NET project; then try calling CreateInstance.

    • Marked as answer by Nils Thomsen Monday, January 27, 2014 8:08 PM
    Sunday, January 26, 2014 8:22 PM
  • I'll try this tomorrow. Thank you so far for your input.
    Sunday, January 26, 2014 8:26 PM
  • I can include the file, but creating an instance at runtime will throw an exception (translated):

    System.BadImageFormatException was not handled.
    Message: An Exception of "System.BadImageFormatException" occured in System.Windows.Forms.dll.
    Additional Information: The file or assambly "CLI_DEMO_PLUGIN, Version=1.0.5140.37317, Culture=neutral, PublicKeyToken=null" or one of it's dependencies was not found. It was tried to load a file with a wrong format.

    Hope this helps?!

    Monday, January 27, 2014 7:47 PM
  • OHHHH YEAAAA I GOT IT!

    C++/CLI Project was compiled to Win32, the rest to Any CPU. That caused the error. Now it finally works!

    Thank you so much!

    Monday, January 27, 2014 8:08 PM