'Calling a native C++ method from C++/CLI

I'm developing Wordle in C++ using a .net graphic interface with visual studio. I have a file.h that contains a class "WordDatabase", and I need to use one of the methods of this class in my main, In order to do this I was trying to create an instance of the object in my main file but it doesn't allow me to do it and it displays this error

 <C++ gcnew cannot allocate an entity of type>

This is the code for the class:

#pragma once
#include <vector>
#include <random>
class WordDatabase
{
    public:
        // Initialises the word database with the associated file
        WordDatabase(std::default_random_engine& randomEngine);
        virtual ~WordDatabase() = default;

        // Returns a random word from the database.
        std::string getRandomWord() const;

};

and this is the code of the main where I call the function

#include "MyForm.h"
#include "WordDatabase.h"
using namespace System;
using namespace System::Windows::Forms;
[STAThread]

void main(array<String^>^ args)
{
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    Project2::MyForm form;
    WordDatabase wdb = gcnew WordDatabase();
    String^ solution = getRandomWord();
    Application::Run(% form);
}


Solution 1:[1]

Following my comments above, here's a complete example of a C++/CLI main using a C++/CLI wrapper class delegating the implementation to a C++ regular class.

In my experience it is better to invest the time and separate the C++ (i.e. native) part, and the C++/CLI (i.e. managed) part.

This is the C++ class header:

// Example.h:
#pragma once
#include <string>
class Example
{
public:
    Example(/*...*/) { /*...*/ }
    std::string GetString();
};

And implementation:

// Example.cpp:
#include "Example.h"
std::string Example::GetString()
{
    return "some_string";
}

And this is the header of the C++/CLI wrapper ref class to be used in a .NET environment:

// ExampleCliWrapper.h
#pragma once
class Example;  // forward declaration
public ref class ExampleCliWrapper
{
public:
    ExampleCliWrapper(/*...*/);
    virtual ~ExampleCliWrapper();
    System::String^ GetString();
private:
    Example * m_pExample;
};

And implementation:

// ExampleCliWrapper.cpp
#include "ExampleCliWrapper.h"
#include "Example.h"
ExampleCliWrapper::ExampleCliWrapper(/*...*/)
{
    m_pExample = new Example(/*...*/);
    //...
}
/*virtual*/ ExampleCliWrapper::~ExampleCliWrapper()
{
    delete m_pExample;
}
System::String^ ExampleCliWrapper::GetString()
{
    std::string strCpp = m_pExample->GetString();
    return gcnew System::String(strCpp.c_str());
}

Note that the last method performed the conversion between std::string and System::String^.

Finally the main that uses it all:

// main.cpp
#include "ExampleCliWrapper.h"
int main(array<System::String ^> ^args)
{
    ExampleCliWrapper ^ exampleCli = gcnew ExampleCliWrapper(/*...*/);
    System::String ^ strCli = exampleCli->GetString();
    System::Console::WriteLine(strCli);
    return 0;
}

Note - I used a raw pointer instead of std::unique_ptr because the C++/CLI compiler does not support using classes like std::unique_ptr (refered to as mixed types). Maybe there's a way around it, not sure.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1