Call C# DLL from C++ application
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

The following article shows you how to accomplish what I need to do using Visual Studio 2005:

https://support.microsoft.com/en-gb/help/828736/how-to-call-a-managed-dll-from-native-visual-c-code-in-visual-studio-n

Attempting the same steps in Visual Studio 2017 results in failure. Errors include:

  • object of abstract class type 'ManagedDLL::ICalculator' is not allowed
  • no instance of constructor matches the argument list
  • cannot instantiate abstract class
  • cannot convert argument 1 from 'const _GUID' to 'const ManagedDLL::ICalculator'

This bounty is to provide a Visual Studio 2017 example of the equivalent code that compiles, runs and works. The C# DLL should be written in .NET Framework 4.6.1.

Do you need managed C++ (CLR) or normal C++ for your code? Also, $10 may just be a bit low for the bounty.
feroldi 4 years ago
Normal C++ - thanks!
Chris Wood 4 years ago
Sorry - forgot to comment on the bounty. I based it on the assumption that the link I provided gives most of the code and that the steps would've changed in some minor ways that elude me.
Chris Wood 4 years ago
I try to code but whenever I defined using MaxElementFn = int(__stdcall *) (int a, int b); in c++ builder I get the following error: E2070 Invalid use of namespace 'MaxElementFn' E2451 Undefined symbol 'MaxElementFn' E2379 Statement missing ; is there a different way to define it in c++ builder?
erika over 2 years ago
awarded to feroldi

Crowdsource coding tasks.

1 Solution

Winning solution

Installing UnmanagedExport with NuGet

  1. Create a C# Class Library solution (required before instaling UnmanagedExport). I'm naming it ExportedCodeSolution for the examples.
  2. Go to Tools > NuGet Package Manager > Package Manager Console.
  3. A console will show up at the bottom of VS. Type in this line:

    Install-Package UnmanagedExports -Version 1.2.7

Setting up solution

NuGet will issue that your solution has no platform target. To change that,
go to the dropdown menu box where it says "Any CPU" (it's side by side with
the Debug/Release dropdown menu box). From there, click on Configuration Manager.
On "Active solution platform", select one of x86, ia64 or x64. If you run a 64 bits
system, select x64. Select x86 otherwise. Then close it.

Now import RGiesecke.DllExport in order to use the attribute.

The following is a code example:

// ExportedCodeSolution.Class1
using System;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace ExportedCodeSolution
{
  public class Class1
  {
    // If you want more examples of this, access:
    // https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

    // You can also use Cdecl and others instead of StdCall.

    [DllExport(ExportName = "maxElement", CallingConvention = CallingConvention.StdCall)]
    static public int maxElement(int a, int b)
    {
      Console.WriteLine("Wow, numbers are {0} and {1}!", a, b);

      if (a > b)
        return a;
      else
        return b;
    }
  }
}

Create a C++ console application solution. Name it however you want.
Use this code as an example to load the exported function.

#include <cstdio>
#include <Windows.h>

// If you used CallingConvention.Cdecl, change this _stdcall to __cdecl.
using MaxElementFn = int(__stdcall *) (int a, int b);

int main()
{
  HMODULE mod = LoadLibraryA("ExportedCodeSolution.dll");
  MaxElementFn maxElement = reinterpret_cast<MaxElementFn>(GetProcAddress(mod, "maxElement"));
  std::printf("max: %d\n", maxElement(1, 2));
}

Note: change your build to use x64 instead of x86. Copy-paste the DLL from
the ExportedCodeSolution directory
ExportedCodeSolution/ExportedCodeSolution/bin/x64/Release/ExportedCodeSolution.dll
to <your C++ solution>/x64/Release/ExportedCodeSolution.dll.

Build and run the C++ solution in Debug > Start Without Debugging. This should be the output from the console:

Wow, numbers are 1 and 2!
max: 2
Press any key to continue . . .

If you get any issues, let me now!

Brilliant! That worked first time! Thanks!
Chris Wood 4 years ago
Thank you ^^
feroldi 4 years ago
Not working for me. Followed exact steps as above, I installed nugget using "Manage Nugget Packages" instead of the command Install-Package but other than that my function retrieved from GetProcAddress is always NULL for some reason. My C# dll function is static and declared as: [DllExport(ExportName = "GetNumber", CallingConvention = CallingConvention.StdCall)] public static int GetNum() {} // calls SOAP My C++ console app calling this C# dll: ```

include "stdafx.h"

include

include

using GetNumberFn = int(__stdcall *)(); int main() { HMODULE mod = LoadLibraryA("SoapDll.dll"); GetNumberFn func= reinterpret_cast<GetNumberFn >(GetProcAddress(mod, "GetNumber")); // ALWAYS NULL std::printf("result: %d\n", func()); } ```
dbnex14 almost 2 years ago
same with @dbnex14. Not working for me either. Always null when GetProcAddress.
vincent1000 over 1 year ago
I don't have access to a windows instance right now, so I can't debug that.
feroldi over 1 year ago
Thanks for the solution! ^^
cocoyen1995 11 months ago