I'm trying to set up a test project to figure out how to correctly wrap a native C++ lib in a managed C++ DLL, to then be called by a C# application.
For my test case I have 3 application:
CPP lib
I compile a library with a class containing four functions.
1) return a double value
2) return a string
3) take a double by reference, modify it.
4) take a string by reference, modify it.
cpp_lib.h
namespace cpp_lib
{
class CPPLibFunctions{
public:
CPPLibFunctions();
public:
static double getValue();
static void incrementValue(double& val);
static std::string getText();
static void changeText(std::string& txt);
};
}
cpp_lib.cpp
#include "cpp_lib.h"
#include <stdexcept>
namespace cpp_lib{
CPPLibFunctions::CPPLibFunctions(){};
double CPPLibFunctions::getValue(){
return 5.5;
}
void CPPLibFunctions::incrementValue(double& val){
val += 1.0;
}
std::string CPPLibFunctions::getText(){
return "success";
}
void CPPLibFunctions::changeText(std::string& txt){
txt += "_123";
}
}
Managed CPP lib
This is a managed C++ project compiled to a DLL, which wraps the functions from cpp_lib.
managed_cpp_lib.h
#include "cpp_lib.h"
#pragma once
#include <msclr\marshal_cppstd.h>
using namespace System;
namespace managed_cpp_lib {
System::String^ stdToSysString(std::string str){
return gcnew System::String(str.c_str());
}
public ref class ManagedCppFunctions
{
private:
cpp_lib::CPPLibFunctions * cppLibFunctions;
public:
ManagedCppFunctions(){
cppLibFunctions = new cpp_lib::CPPLibFunctions();
}
double getValue(){
return cppLibFunctions->getValue();
}
void incrementValue(double& val){
cppLibFunctions->incrementValue(val);
}
System::String^ getText(){
return stdToSysString(cppLibFunctions->getText());
}
void changeText(System::String^ txt){
//this does not work:
std::string txtstd = msclr::interop::marshal_as<std::string>(txt);
cppLibFunctions->changeText(txtstd);
txt = stdToSysString(txtstd);
}
};
}
csharp_app
Lastly, cssharp_app is a C# console application, which references managed_cpp_lib, and calls the functions.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using managed_cpp_lib;
namespace csharp_app
{
class Program
{
static void Main(string[] args)
{
managed_cpp_lib.ManagedCppFunctions managedCppFunctions = new managed_cpp_lib.ManagedCppFunctions();
//works:
double val = managedCppFunctions.getValue();
Console.WriteLine("\managedCppFunctions.getValue() = {0}", val);
//works:
string txt = managedCppFunctions.getText();
Console.WriteLine("\managedCppFunctions.getText() = {0}", txt);
//does not work:
/*managedCppFunctions.incrementValue(val);
Console.WriteLine("\managedCppFunctions.incrementValue(val) = {0}", val);*/
//the string is not modified:
managedCppFunctions.changeText(txt);
Console.WriteLine("\managedCppFunctions.changeText(txt) = {0}", txt);
Console.WriteLine("...");
}
}
}
The output of csharp_app is:
managedCppFunctions.getValue() = 5.5
managedCppFunctions.getText() = success
managedCppFunctions.changeText(txt) = success
So managedCppFunctions.getValue()
and managedCppFunctions.getText()
works.
managedCppFunctions.changeText(txt)
does not modify the content of the string.
I'm not sure how to implement managedCppFunctions.incrementValue(val)
.
What is the correct way to pass a double and a string by reference, to then change their values using managed C++ and C#?