Here is a simple example with 3 files
- DLL in C#
- interface program in C++/CLR
- main program in C++
First the C# DLL. This will be built as a DLL.
using System;
using System.Collections.Generic;
using System.Text;
namespace csdll
{
public class ReturnValues
{
public void CSGetInt(ref int x)
{
x = 42;
}
public void CSGetStr(ref string s)
{
s = "Hey it works";
}
}
}
Now the interface program. This is the glue logic. This has to be compiled as C++/CLR but can be in the same project as main: just not in the same file as it has to be compiled differently. Under General in Common Language Runtime Support, select Common Language Runtime Support (/clr).
#include <string>
#include <msclr\marshal_cppstd.h>
#using "csdll.dll"
using namespace System;
extern void cppGetInt(int* value)
{
csdll::ReturnValues^ rv = gcnew csdll::ReturnValues();
rv->CSGetInt(*value);
}
extern void cppGetStr(std::string& value)
{
System::String^ csvalue;
csdll::ReturnValues^ rv = gcnew csdll::ReturnValues();
rv->CSGetStr(csvalue);
value = msclr::interop::marshal_as<std::string>(csvalue);
}
Now the main program.
#include "stdafx.h"
#include <iostream>
#include <string>
// These can go in a header
extern void cppGetInt(int* value);
extern void cppGetStr(std::string& value);
int _tmain(int argc, _TCHAR* argv[])
{
int value = 99;
std::string svalue = "It does not work";
cppGetInt(&value);
std::cout << "Value is " << value << std::endl;
cppGetStr(svalue);
std::cout << "String value is " << svalue << std::endl;
return 0;
}
Set the dependency to the DLL.
Set the build platform to Mixed Platforms not win32 or any CPU. If it is set to any of those, something won't build. Run it and you will get
Value is 42
String value is Hey it works