'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 |