Search code examples
c#.netdllc++-cliclr

Call .NET dll from C++ code failes when calling GetProcAddress(...)


I want to call a method of .NET dll (v4.5) from C++ code. This dll uses a third party dll (SKCLNET .NET v1.0)

I build a simple C++ code for that (see below). The problem is that GetProcAddress(...) returns NULL for some reason. I'm not sure what is wrong with the code...

I tried to invoke the dll-function via .NET-Console-App directly this worked fine.

#include "pch.h"
#include <iostream>
#include <Windows.h>

using namespace System;

typedef std::string(*GetLicenseStatusFunction)();

int main(array<System::String ^> ^args)
{
    HMODULE hDLL = LoadLibrary(L"LicenseCheck.dll");

    if (hDLL == NULL) {
        std::cout << "Error loading the DLL" << std::endl;
        return 1;
    }

    GetLicenseStatusFunction pGetLicenseStatus = (GetLicenseStatusFunction)GetProcAddress(hDLL, "ValidateLicense.GetLicenseStatus");

    if (pGetLicenseStatus == NULL) {
        std::cout << "Error getting the function pointer" << std::endl;
        return 1;
    }

    std::string result = pGetLicenseStatus();
    std::cout << result << std::endl;

    return 0;
}

Here the structure of the used dll:

enter image description here

Here the ValidateLicense class in the .NET dll with the function GetLicenseStatus() I would like to access. enter image description here


Solution

  • From using namespace System; and the prototype of main,
    I assume this is a C++/CLI project (and not a native C++ one).

    Since using C++/CLI means it is a .NET project, you can consume other .NET assemblies similarly to the way you would do that in C#. Just use "add reference" from the project tree and add the assembly you want to consume.

    LoadLibrary() and GetProcAddress() are used only to load and call native functions, from native code. As explained above this is not the case here.

    Note that in C++/CLI reference types use the handle to object operator (^). So from C++/CLI side the method ValidateLicense.GetLicenseStatus returns a String^.
    Also in C++/CLI use :: instead of . for scopes of namespaces and classes:

    using namespace ....
    //...
    String^ sts = ValidateLicense::GetLicenseStatus();
    

    In order to print it you can use:

    Console::WriteLine(sts);
    

    You can also convert it to a native std::string:

    #include <string>
    #include <msclr/marshal_cppstd.h>
    //...
    std::string sts_cpp = msclr::interop::marshal_as<std::string>(sts);