I implemented this using C++ CLI wrapper. C++ CLI is one the three possible approaches for C++ C# interop. The other two approaches are P/Invoke and COM. (I have seen a few good people recommend using C++ CLI over the other approaches)
In order to marshall information from native code to managed code, you need to first wrap the native code inside a C++ CLI managed class. Create a new project to contain native code and its C++ CLI wrapper. Make sure to enable the /clr
compiler switch for this project. Build this project to a dll. In order to use this library, simply add its reference inside C# and make calls against it. You can do this if both projects are in the same solution.
Here are my source files for a simple program to marshal a std::vector<double>
from native code into C# managed code.
1) Project EntityLib (C++ CLI dll) (Native Code with Wrapper)
File NativeEntity.h
#pragma once
#include <vector>
class NativeEntity {
private:
std::vector<double> myVec;
public:
NativeEntity();
std::vector<double> GetVec() { return myVec; }
};
File NativeEntity.cpp
#include "stdafx.h"
#include "NativeEntity.h"
NativeEntity::NativeEntity() {
myVec = { 33.654, 44.654, 55.654 , 121.54, 1234.453}; // Populate vector your way
}
File ManagedEntity.h (Wrapper Class)
#pragma once
#include "NativeEntity.h"
#include <vector>
namespace EntityLibrary {
using namespace System;
public ref class ManagedEntity {
public:
ManagedEntity();
~ManagedEntity();
array<double> ^GetVec();
private:
NativeEntity* nativeObj; // Our native object is thus being wrapped
};
}
File ManagedEntity.cpp
#include "stdafx.h"
#include "ManagedEntity.h"
using namespace EntityLibrary;
using namespace System;
ManagedEntity::ManagedEntity() {
nativeObj = new NativeEntity();
}
ManagedEntity::~ManagedEntity() {
delete nativeObj;
}
array<double>^ ManagedEntity::GetVec()
{
std::vector<double> tempVec = nativeObj->GetVec();
const int SIZE = tempVec.size();
array<double> ^tempArr = gcnew array<double> (SIZE);
for (int i = 0; i < SIZE; i++)
{
tempArr[i] = tempVec[i];
}
return tempArr;
}
2) Project SimpleClient (C# exe)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EntityLibrary;
namespace SimpleClient {
class Program {
static void Main(string[] args) {
var entity = new ManagedEntity();
for (int i = 0; i < entity.GetVec().Length; i++ )
Console.WriteLine(entity.GetVec()[i]);
}
}
}