0

I have a C++ Windows application developped with RAD Studio (C++Builder) XE4. It has some plugins, which are DLLs (always written with RAD Studio) that are dynamically loaded with this technique.

Now in one of this plugins I need reflection capabilities. While it seems I cannot achieve them with C++ (reflection is needed on a third-party COM DLL that I cannot modify) I decided to rewrite this plugin in C# (which has powerful reflection capabilities), thus creating a .NET assembly.

I know I should expose the assembly via COM, but I can't (we don't want to change the way the main application loads all DLLs).

My aim is to dynamically load the .NET assembly and invoke its functions (for instance here we call SetParam function) with something like the following, like I do with the other plugins.

//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/assembly.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "_SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());

where ptr_SetParam is defined as

typedef int(*ptr_SetParam)(const wchar_t*, const wchar_t*);

Is there a way?

bluish
  • 26,356
  • 27
  • 122
  • 180
  • 2
    [There are ways](http://stackoverflow.com/questions/17127825/c-sharp-unmanaged-exports) to bolt unmanaged exports onto a C# assembly. Giesecke's tool gets used a lot. Beware that this is almost never not a drastic mistake, it scales poorly and exceptions are exceedingly difficult to diagnose. – Hans Passant Sep 10 '15 at 15:40

1 Answers1

1

Thanks to @HansPassant's comment I found a way.

I created following Visual Studio projects.

MyDllCore .NET assembly project, written in C# or any other .NET language. Here I have my managed class like the following, where the real logic of the assembly is implemented.

using System;
using System.Collections.Generic;
//more usings...

namespace MyNamespace
{
    public class HostDllB1
    {
        private Dictionary<string, string> Parameters = new Dictionary<string, string>();

        public HostDllB1()
        {
        }

        public int SetParam(string name, string value)
        {
            Parameters[name] = value;
            return 1;
        }
    }
}

MyDllBridge DLL project, written in C++/CLI, with /clr compiler option. It is just a "bridge" project, it has a dependancy on MyDllCore project and has just one .cpp o .h file like the following, where I map the methods from the program that loads the DLL to the methods in the .NET assembly.

using namespace std;
using namespace System;
using namespace MyNamespace;
//more namespaces...

#pragma once
#define __dll__
#include <string.h>
#include <wchar.h>
#include "vcclr.h"
//more includes...

//References to the managed objects (mainly written in C#)
ref class ManagedGlobals 
{
public:
    static MyManagedClass^ m = gcnew MyManagedClass;
};

int SetParam(const wchar_t* name, const wchar_t* value) 
{
    return ManagedGlobals::m->SetParam(gcnew String(name), gcnew String(value));
}

Finally I have a C++Builder program that loads MyDllBridge.dll and uses its methods calling them like in the following.

//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/MyDllBridge.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());
bluish
  • 26,356
  • 27
  • 122
  • 180