Вызов управляемой C ++ lib из C # с передачей значений по ссылке - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь настроить тестовый проект, чтобы выяснить, как правильно обернуть нативную C ++ lib в управляемую C ++ DLL, чтобы затем вызывать ее из приложения C #.

Для моего тестового примера у меня есть 3 приложения:

CPP lib

Я компилирую библиотеку с классом, содержащим четыре функции.

1) вернуть двойное значение

2) вернуть строку

3) Возьмите дубль по ссылке, измените его.

4) взять строку по ссылке, изменить ее.

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";
   }
}

Управляемая библиотека CPP

Это управляемый проект C ++, скомпилированный в DLL, который оборачивает функции из 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

Наконец, cssharp_app - это консольное приложение C #, которое ссылается на managed_cpp_lib и вызывает функции.

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("...");
        }
    }
}

Вывод csharp_app :

managedCppFunctions.getValue() = 5.5
managedCppFunctions.getText() = success
managedCppFunctions.changeText(txt) = success

Так managedCppFunctions.getValue() и managedCppFunctions.getText() работает.

managedCppFunctions.changeText(txt) не изменяет содержимое строки.

Я не уверен, как реализовать managedCppFunctions.incrementValue(val).

Как правильно передать значение типа double и строку по ссылке, чтобы затем изменить их значения, используя управляемые C ++ и C #?

...