0

I am working in C++ and creating library which analyses the data. I have created few classes which have functions taking C++ vector. Now I want to create UI in C# and call these classes. I am thinking to create API to call from C#.

Since data are arrays/vector then how can I call it from C#?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
CrazyC
  • 1,840
  • 6
  • 39
  • 60
  • When you say C++ vector are you talking about `std::vector` then? – Dirk May 31 '13 at 19:03
  • Interoperability is kindof an "Advanced topic" but what you want is definitely possible. The trick is to make a "managed wrapper" around your unmanaged c++ clode You can use IJW with c++\cli [http://stackoverflow.com/questions/15672351/calling-c-function-from-c-with-lots-of-complicated-input-and-output-paramete/15685123#15685123] or, if you have c style called, link to the dll directly using /pinvoke [http://msdn.microsoft.com/en-us/magazine/cc164123.aspx]. – IdeaHat May 31 '13 at 19:03
  • I am using std::vector and inside the class their is heavy use of BOOST library. – CrazyC May 31 '13 at 19:07
  • Another option is to wrap the C++ library in a COM interface, then from C# add it as a reference, the interop layer is generated automatically – PeskyGnat May 31 '13 at 19:10

2 Answers2

0

I would have just made this a comment, but my rep isn't high enough. There are some complications when using STL classes (such as vector or string) in a class library with C++. You can check here for some more info and possible solutions: I can pass std::string for a Dll and what i can do with DLL´s?

Community
  • 1
  • 1
Mike
  • 346
  • 2
  • 10
0

You need to create your own C++/CLI interop to achieve this.

Strongly recommend a nice book, "Expert C++/CLI" by Marcus Heege, quite a good read.

Here's my brief example:

// Program.cs
static void Main(string[] args)
{
    List<string> someStringList = new List<string>();
    someStringList.Add("Betty");
    someStringList.Add("Davis");
    someStringList.Add("Eyes");

    NativeClassInterop nativeClass = new NativeClassInterop();
    string testString = nativeClass.StringCat(someStringList);
}

// NativeClass.h, skipping this, it's obvious anyways

// NativeClass.cpp, normal C++ class, this was in some DLL project, don't need exports
#include "stdafx.h"
#include "NativeClass.h"
std::string NativeClass::StringCat(std::vector<std::string> stringList)
{
    std::string result = "";
    for(unsigned int i = 0; i < stringList.size(); i++)
    {
        if(i != 0)
        {
            result += " ";
        }
        result += stringList[i];
    }
    return result;
}

// NativeClassInterop.cpp, in same DLL project, but compile this file with /clr switch
#include <gcroot.h>
#using <System.dll>
#include <vector>
#include <string>
#include "NativeClass.h"

// Helper method
static std::string nativeStringFromManaged(System::String^ str)
{
    System::IntPtr hGlobal =
        System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str);

    std::string nativeString((hGlobal.ToPointer() == 0) 
        ? "" : (char*)hGlobal.ToPointer());

    System::Runtime::InteropServices::Marshal::FreeHGlobal(hGlobal);
    return nativeString;
}

// C++/CLI wrapper class
public ref class NativeClassInterop
{
public:
    System::String^ StringCat(System::Collections::Generic::List<System::String^>^ someStringList)
    {
        // You get to do the marshalling for the inputs
        std::vector<std::string> stringList;
        for(int i = 0; i < someStringList->Count; i++)
        {
            stringList.push_back(nativeStringFromManaged(someStringList[i]));
        }

        NativeClass nativeClass;
        std::string nativeString = nativeClass.StringCat(stringList);

        // And for the outputs ;-)
        System::String^ managedString = gcnew System::String(nativeString.c_str());
        return managedString;
    }
};
Chris O
  • 5,017
  • 3
  • 35
  • 42