Using C# from native C++ with the help of C++/CLI (fixed and enhanced)

Archive fileVS Solution(all the credits for Tim Anderson)

Important note

This article replaces the previous one with the same title.
Indeed the previous C++/CLI wrapper implementation had a flaw that created memory corruption.
This issue has been fixed in the following implementation.
Moreover I’ve used it as an opportunity to greatly enhance the content, especially the description of the C++/CLI wrapper implementation, design rationales being now included.

Update note

The article has been updated on the 19th of June 2016 to integrate 3 fixes:

  • the YahooAPIWrapper‘s destructor is correctly declared in the header file to avoid memory leaks,
  • the YahooAPIWrapper‘s definition/cpp file does not redefine the class and the __declspec(dllexport) metadata has been moved to the header file to avoid compilation errors,
  • the YahooAPIWrapper‘s and native C++ program’s implementations have been updated to take into account the new fields names of Yahoo API to avoid runtime exceptions.

Introduction

When it comes to software development in a professional environment, heterogeneity is the rule not the exception: you often need to interact with systems developed with other technologies.

I’ve been recently faced with such a situation: a team that uses only native C++ needed to retrieve data using the object-oriented API of another team that develops only in .Net with C#.
This is a relatively uncommon scenario (just look at the number of articles on the subject), the standard case being new systems based on the .Net platform, developed in C# or VB.Net, needing to interact with legacy systems developed in native C++.

I’ve used the C++/CLI platform due to its unique ability to mix managed (.Net) and native code in one place and is then the ideal tool for building bridges between these two worlds using simple wrappers: the native face of the wrapper can be consumed by the legacy components and its managed face can directly use the C# API.

In this article I’ll illustrate how I’ve tackled the issue by building a simple C++/CLI wrapper, using a similar use-case: market-data retrieval from Yahoo.

(All the source code of this article is available in this ZIP archive)

The C# library

Here is a simple C# class that retrieves financial data using the Yahoo finance API.

Source code

using System.Net; // WebClient
using System.Globalization; // CultureInfo

public class YahooAPI
{
    private static readonly WebClient webClient = new WebClient();

    private const string UrlTemplate = "http://finance.yahoo.com/d/quotes.csv?s={0}&f={1}";

    private static double ParseDouble(string value)
    {
         return double.Parse(value.Trim(), CultureInfo.InvariantCulture);
    }
    
    private static string[] GetDataFromYahoo(string symbol, string fields)
    {
        string request = string.Format(UrlTemplate, symbol, fields);

        string rawData = webClient.DownloadString(request).Trim();
        
        return rawData.Split(',');
    }

    public double GetBid(string symbol)
    {
        return ParseDouble(GetDataFromYahoo(symbol, "b")[0]);
    }

    public double GetAsk(string symbol)
    {
        return ParseDouble(GetDataFromYahoo(symbol, "a")[0]);
    }
    
    public string GetCapitalization(string symbol)
    {
        return GetDataFromYahoo(symbol, "j1")[0];
    }
    
    public string[] GetValues(string symbol, string fields)
    {
        return GetDataFromYahoo(symbol, fields);
    }
}

Nothing to notice that has to do with our problematic, this is just plain-vanilla C#.

Compilation

We compile it to obtain our “YahooAPI.dllmanaged DLL:

csc /target:library YahooAPI.cs
Microsoft (R) Visual C# Compiler version 4.0.30319.17929
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

The C++/CLI wrapper

Header file

Here is the header file (that will be consumed by the C++/CLI and native C++ codes) for the wrapper:

class YahooAPIWrapperPrivate;

class __declspec(dllexport) YahooAPIWrapper
{
    private: YahooAPIWrapperPrivate* _private;

    public: YahooAPIWrapper();

    public: ~YahooAPIWrapper();
    
    public: double GetBid(const char* symbol);

    public: double GetAsk(const char* symbol);
    
    public: const char* GetCapitalization(const char* symbol);
    
    public: const char** GetValues(const char* symbol, const char* fields);
};

Nothing special except:

  • the “__declspec(dllexport)” metadata that asks the compiler to publicly export the whole interface of the class and to generate a “.lib file we’ll use to link the native C++ program with the C++/CLI DLL
  • the forward declaration of the “YahooAPIWrapperPrivate” class, needed so that the compiler knows “YahooAPIWrapperPrivate” refers to some class defined somewhere; where it is and what it is is irrelevant for the compiler at this stage, it only needs to know it has to emit code that allocates a memory area whose size is the size of any pointer on this platform.

Source code

Here comes the interesting part, our C++/CLI wrapper that uses the C# library:

#using "YahooAPI.dll"

#include <msclr\auto_gcroot.h>

#include "YahooAPIWrapper.h"

using namespace System::Runtime::InteropServices; // Marshal

class YahooAPIWrapperPrivate
{
    public: msclr::auto_gcroot<YahooAPI^> yahooAPI;
};

YahooAPIWrapper::YahooAPIWrapper()
{
    _private = new YahooAPIWrapperPrivate();
    _private->yahooAPI = gcnew YahooAPI();
}

double YahooAPIWrapper::GetBid(const char* symbol)
{
    return _private->yahooAPI->GetBid(gcnew System::String(symbol));
}

double YahooAPIWrapper::GetAsk(const char* symbol)
{
    return _private->yahooAPI->GetAsk(gcnew System::String(symbol));
}

const char* YahooAPIWrapper::GetCapitalization(const char* symbol)
{
    System::String^ managedCapi = _private->yahooAPI->GetCapitalization(gcnew System::String(symbol));

    return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();
}

const char** YahooAPIWrapper::GetValues(const char* symbol, const char* fields)
{
    cli::array<System::String^>^ managedValues = _private->yahooAPI->GetValues(gcnew System::String(symbol), gcnew System::String(fields));

    const char** unmanagedValues = new const char*[managedValues->Length];

    for (int i = 0; i < managedValues->Length; ++i)
    {
        unmanagedValues[i] = (const char*)Marshal::StringToHGlobalAnsi(managedValues[i]).ToPointer();
    }

    return unmanagedValues;
}

YahooAPIWrapper::~YahooAPIWrapper()
{
    delete _private;
}

Some explanations:

  • the hats “^” represent managed references, i.e. they point to managed objects (like “System::String“) allocated on the managed heap; they are to managed objects what native pointers are to native objects allocated on the native heap
  • the “gcnew” operator is used for allocating objects on the managed heap, whereas the “new” operator allocates only on the native heap
  • cli::array” is the C++/CLI representation of a managed array
  • auto_gcroot” is a wrapper around a managed reference: you can’t directly embed a managed reference inside a native type especially because the way memory is handled in the native and managed worlds is quite different; moreover, compared to “gcroot“, which too avoid explicit management like pinning, “auto_gcroot” is automatically disposed when going out of scope
  • the “StringToHGlobalAnsi” method converts a managed “System::String” which is made of UTF-16 chars to an array of ANSI chars it allocates on the native heap; it returns a pointer to this array as an “IntPtr” which is a managed wrapper around a native pointer that we obtain with the “ToPointer” method as a “void*
  • moreover you may wonder why we use “const char*” instead of “std::string“: because publicly exposing STL types is brittle as their implementation could differ from vendor to vendor and even between different versions from the same vendor

Well, after all, there is quite a bunch of things to explain. 🙂
But if you use C++/CLI on a regular basis you’ll quickly become familiar with this at first cryptic stuff.

Design rationales

You may have one more question: why the gcroot field has been isolated in its own structure?
First you should know that in native C++ you must declare all the members of a type, including the private part.
This may seem strange to C# programmers, because in C# the private part is hidden; but for native C++, header files are more than a simple description of the interface of the types, they describe their memory structure too, then all the information must be available to the calling code so that it is able to correctly allocate the memory for the instances of the types, otherwise you’ll get memory corruption (believe me you don’t want to live such a situation ;)).

But in that case, why not simply add the gcroot field to the class declaration?
Because “gcroot” is pure C++/CLI stuff that has no sense for native C++ so your code won’t even compile; moreover, even if it compiled, this would be an ugly leak of the abstraction we’re trying to build.
With this design we’ve hidden all the C++/CLI stuff inside the “YahooAPIWrapperPrivate” structure so that our wrapper has an interface compatible with native C++.
Finally, I’ve later discovered that I’ve only reinvented the wheel: the PIMPL principle used in native C++ development; so it seems like one more compelling argument in favor of this design.

OK for using an additional structure, but why a pointer to the structure instead of an instance?
Because as I’ve said you must fully describe the memory layout of your types, this includes the memory layout of objects inlined into the types, so here the compiler of the native C++ code should have to know the layout of the “YahooAPIWrapperPrivate” type too, so it should know about … gcroot.
We have not this issue with pointers because they all have the same size; indeed the values of pointers are memory addresses: their size depends only on the platform (Intel 8088 (16 bits), x86/IA-32 (32 bits), IA-64 (64 bits)…); then the compiler can allocate a fixed amount of memory per pointer without having to worry about the objects pointed to.

Compilation

Here is how to compile the C++/CLI wrapper:

cl /clr /LD YahooAPIWrapper.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01
for Microsoft (R) .NET Framework version 4.00.30319.18034
Copyright (C) Microsoft Corporation.  All rights reserved.

YahooAPIWrapper.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:YahooAPIWrapper.dll
/dll
/implib:YahooAPIWrapper.lib
YahooAPIWrapper.obj
   Creating library YahooAPIWrapper.lib and object YahooAPIWrapper.exp
  • /clr” triggers the C++/CLI mode, by default CL acts as a native C++ compiler
  • /LD” asks CL to generate a DLL instead of an EXE

We now have our “YahooAPIWrapper.dllDLL ready to be used.

The native C++ application

Finally here is the native C++ application that uses the C# API through the C++/CLI wrapper.

Source code

#include <iostream>

#include "YahooAPIWrapper.h"

int main()
{
    const char* stock = "GOOG";
    YahooAPIWrapper yahoo;
    
    double bid = yahoo.GetBid(stock);
    double ask = yahoo.GetAsk(stock);
    const char* capi = yahoo.GetCapitalization(stock);
    
    const char** bidAskCapi = yahoo.GetValues(stock, "abj1");
    
    std::cout << "Bid: " << bid << std::endl;
    std::cout << "Ask: " << ask << std::endl;
    std::cout << "Capi: " << capi << std::endl;
    
    std::cout << "BidAskCapi[0]: " << bidAskCapi[0] << std::endl;
    std::cout << "BidAskCapi[1]: " << bidAskCapi[1] << std::endl;
    std::cout << "BidAskCapi[2]: " << bidAskCapi[2] << std::endl;
}

Compilation

Compilation is straightforward:

cl test.cpp YahooAPIWrapper.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\xlocale(323) : wa
rning C4530: C++ exception handler used, but unwind semantics are not enabled. S
pecify /EHsc
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj
YahooAPIWrapper.lib
   Creating library test.lib and object test.exp

As you can see, from the point of view of the native C++ application, things are transparent (be it the source code or the compilation process), there is no trace of any .Net stuff (except the name of the wrapper I’ve deliberately made explicit), just a plain old native C++ API.

Execution

And here are the results:

test.exe
Bid: 821.2
Ask: 822
Capi: 270.8B
BidAskCapi[0]: 821.20
BidAskCapi[1]: 822.00
BidAskCapi[2]: 270.8B

Returning data structures

Following a question in the comments, I’ve built a small sample to illustrate how you could return data-structures instead of simple types and arrays.

The C# library

using System; // Random

namespace StockMarket
{
	public struct Quote
	{
		public double Bid { get; set; }
		public double Mid { get; set; }
		public double Ask { get; set; }
		public double Capitalization { get; set; }
	}

	public class API
	{
		private Random randomGenerator = new Random();
		
		public Quote GetQuote(string symbol)
		{
			double mid = randomGenerator.Next(95, 105);
			
			return new Quote
			{
				Bid = mid - 0.1,
				Mid = mid,
				Ask = mid + 0.1,
				Capitalization = mid * 10e6
			};
		}
	}
}

The C++/CLI wrapper

Header file

class StockMarketAPIWrapperPrivate;

struct __declspec(dllexport) Quote
{
	double bid;
	double mid;
	double ask;
	double capitalization;
};

class __declspec(dllexport) StockMarketAPIWrapper
{
    private: StockMarketAPIWrapperPrivate* _private;

    public: StockMarketAPIWrapper();

    public: ~StockMarketAPIWrapper();
    
    public: const Quote GetQuote(const char* symbol);
};

Quote is the native equivalent of the managed StockMarket.Quote data-structure.

Definition file

#using "StockMarketAPI.dll"

#include <msclr\auto_gcroot.h>

#include "StockMarketAPIWrapper.h"

class StockMarketAPIWrapperPrivate
{
    public: msclr::auto_gcroot<StockMarket::API^> API;
};

StockMarketAPIWrapper::StockMarketAPIWrapper()
{
    _private = new StockMarketAPIWrapperPrivate();
    _private->API = gcnew StockMarket::API();
}

const Quote StockMarketAPIWrapper::GetQuote(const char* symbol)
{
    StockMarket::Quote managedQuote = _private->API->GetQuote(gcnew System::String(symbol));

    Quote nativeQuote;
    nativeQuote.bid = managedQuote.Bid;
    nativeQuote.mid = managedQuote.Mid;
    nativeQuote.ask = managedQuote.Ask;
    nativeQuote.capitalization = managedQuote.Capitalization;

    return nativeQuote;
}

StockMarketAPIWrapper::~StockMarketAPIWrapper()
{
    delete _private;
}

The native C++ application

#include <iostream>

#include "StockMarketAPIWrapper.h"

int main()
{
    const char* stock = "GOOG";

    StockMarketAPIWrapper API;
    
    Quote quote = API.GetQuote(stock);
    
    std::cout << "Bid: " << quote.bid << std::endl;
	std::cout << "Mid: " << quote.mid << std::endl;
    std::cout << "Ask: " << quote.ask << std::endl;
    std::cout << "Capi: " << quote.capitalization << std::endl;
}

Compilation

C# library

csc /target:library StockMarketAPI.cs
Compilateur Microsoft (R) Visual C# version 1.3.1.60616
Copyright (C) Microsoft Corporation. Tous droits réservés.

C++/CLI wrapper

cl /clr /LD StockMarketAPIWrapper.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1
for Microsoft (R) .NET Framework version 4.07.2633.0
Copyright (C) Microsoft Corporation.  All rights reserved.

StockMarketAPIWrapper.cpp
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:StockMarketAPIWrapper.dll
/dll
/implib:StockMarketAPIWrapper.lib
StockMarketAPIWrapper.obj
   Creating library StockMarketAPIWrapper.lib and object StockMarketAPIWrapper.exp

Native C++ application

cl test.cpp StockMarketAPIWrapper.lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xlocale(341): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\exception(359): warning C4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj
StockMarketAPIWrapper.lib
   Creating library test.lib and object test.exp

Execution

Here are some samples of runs:

test.exe
Bid: 103.9
Mid: 104
Ask: 104.1
Capi: 1.04e+09

test.exe
Bid: 101.9
Mid: 102
Ask: 102.1
Capi: 1.02e+09

test.exe
Bid: 99.9
Mid: 100
Ask: 100.1
Capi: 1e+09

Conclusion

As you’ve seen, using C++/CLI wrappers for native to managed interop is rather straightforward, the only difficulty being the plumbing code necessary for converting to and from managed types.
The other way around, that is managed to native interop, is almost identical except that you’ll wrap native objects and that the called side will be managed and the calling side will be native.

Though wrapping with C++/CLI is quite simple it remains a tedious and error-prone process: imagine if you need to export dozens or more managed classes!
You could of course factorize the repetitive code, like conversions, by building helpers but you’ll still need to implement the classes’ structures by-hand, so unless you have few types you should not go down this path.

Fortunately there is tools, like SWIG, that can automate the process for this kind of scenario by generating the plumbing layer; they will isolate you from a significant part of the low-level details, probably avoiding you some headaches (maybe causing others ;)), so taking the time to learn them should be worth it on the long term if you have a big project.

If you’ve used this approach in a real-life project too, I’d be really interested in hearing from you, so please let a comment with your feedback.
If you have any remark, question or suggestion feel free to let a comment as well.

Thanks for reading! 🙂

233 thoughts on “Using C# from native C++ with the help of C++/CLI (fixed and enhanced)

  1. Having read your article, “Using C# from native C++ with the help of C++/CLI”,
    I created a C# class:

    namespace foo
    {
    public class Class1
    {
    public void Method1()
    {
    Console.WriteLine(“Method1”);
    }
    }

    I built it into MyDll.dll.

    I created a C++ header called Wrapper.h:

    #using “MyDll.dll”
    #include
    using namespace System::Runtime::InteropServices;
    class __declspec(dllexport) Wrapper
    {
    private: msclr::auto_gcroot myDll;
    };

    and a C++ file, Wrapper.cpp:

    #include “wrapper.h”
    void Wrapper::Method1()
    {
    }

    There is also an empty (as of now) C++ file which will correspond to your test.cpp file. All three projects are contained within the same solution.

    But the solution won’t build; I get these error messages, which refer to the wrapper.h file:

    error C2065: ‘MyDll’ : undeclared identifier
    error C2059: syntax error : ‘>’
    error C2143: syntax error : missing ‘;’ before ‘}’

    They refer to this line:
    private: msclr::auto_gcroot myDll;

    If I comment out this line, then the solution builds. What am I doing wrong?

    Robert Rotstein

        • Hi,
          if I remember well there was an issue in the initial version of the article.
          Are you using the latest version of the code?
          If so can you please share your code, or a similar one that reproduce the issue?
          Thanks.
          Mickael

      • I also have the same problem when compiling the source codes. It prompts “1>StringClassWrapper.cpp(11): error C2065: ‘StringClass’ : undeclared identifier
        1>StringClassWrapper.cpp(11): error C2059: syntax error : ‘>'”
        I use MS VS C++ 2010 Express to develop.

      • Hi,
        the article has been updated twice since then and I’ve not heard of this issue again.
        Could you please give more details.

        • eroor is

          fatal error C1190: managed targeted code requires a ‘/clr’ option

          and if u can provide me ur email i can mail you the project

          • There is plenty of issues with the code:

            • for Chrome you should target “Address and search bar” instead of “Search or enter address” which is for Firefox
            • the methods’ names are not consistent: should be GetUrl instead of GetBid
            • same for he return type, wchar_t* seems good:
              wchar_t* chromeWrapper::GetUrl()
              {
                  return (wchar_t*)Marshal::StringToHGlobalAuto(_private->ChromeUrl->GetUrl()).ToPointer();
              }
            • the namespaces are missing: msclr::auto_gcroot<chrome::ChromeUrl^> and gcnew chrome::ChromeUrl()

            Here is the fixed wrapper :

            #include <msclr\auto_gcroot.h>
            
            #include "chromeurl.h"
            
            using namespace System::Runtime::InteropServices;
            
            class chromeWrapperPrivate
            {
                public: msclr::auto_gcroot<chrome::ChromeUrl^> ChromeUrl;
            };  
            
            chromeWrapper::chromeWrapper()
            {
                _private = new chromeWrapperPrivate();
                _private->ChromeUrl = gcnew chrome::ChromeUrl();
            }
            
            wchar_t* chromeWrapper::GetUrl()
            {
                return (wchar_t*)Marshal::StringToHGlobalAuto(_private->ChromeUrl->GetUrl()).ToPointer();
            }
            
            chromeWrapper::~chromeWrapper()
            {
                delete _private;
            }

            And a native C++ main that works with the fixes:

            #include <iostream>
            #include "chromeurl.h"
            
            int main()
            {
                chromeWrapper w;
                wchar_t* url = w.GetUrl();
                std::wcout << url << std::endl;
            }
      • hey thanks for the reply
        but I have a question Now. Yesterday i solve that problem by adding my c# project as a reference so my ques. is that .. do I need to do that(adding my c# project as a reference).

        Really thanks for you solution again….

        • Yes I’ve too added it as a reference which seems the right solution to benefit from VS integration and automation.

          So you can stick with it.

    • As you return string , int , double , can you please give a example to return class .
      Like we have a class in c# , with 2-3 properties , I want to return this call in managed c++ .

      • Hi Shakir,
        following your comment I’ve added a full section for this use-case.
        Have a look at it, hopefully it will do the job. 🙂

  2. Hello,
    Thanks for the info. I am unable to add iostream header in the mananged wrapper of the c++/cli. The inclusion brings the error when built:
    C:\Programs\Microsoft Visual Studio 10.0\VC\include\eh.h(78): error C2059: syntax error : ‘(‘.

    How to solve this?

    • Hello,

      what is the extension of your file?
      If you’ve used “.c” you can either:
      – change it for “.cpp”
      – compile with the “/Tp” (note the upper “T”) option to help “cl” understand you’re working with C++: cl /Tp test.c YahooAPIWrapper.lib

      Let me know if your issue is fixed…

      Thanks

  3. Hi,
    Thanks for the info.
    File ext is .cpp, The project builds when #include is commented,
    Using /Tp did not help same error…:-(

    • Are you using VS to build?
      If yes, please check the setting: “Properties -> C/C++ -> Advanced -> Compile As -> Compile as C++ Code”

  4. I have tried your source code and Compiled a DLL, When I tried to call the DLl from my python code it gives me a error of Method ‘GetAsk’ not found. could you please explain how can I expose the method GetAsk to the non C++ functions?

    • Hi John, thanks for reading

      The Yahoo wrapper is a class so its methods are not directly usable from Python.

      A possible solution is to create a C interface:

      extern "C"
      {
          __declspec(dllexport) void* YahooAPIWrapper_New()
          {
      	return new(std::nothrow) YahooAPIWrapper();
          }
      	
          __declspec(dllexport) void YahooAPIWrapper_Delete(void* wrapper)
          {
      	delete wrapper; 
          }
      	
          __declspec(dllexport) double YahooAPIWrapper_GetBid(void* wrapper, const char* symbol)
          {
              return reinterpret_cast(wrapper)->GetBid(symbol);
          }
      }
      

      And we should be able to use it like this:

      import ctypes
      
      lib = ctypes.WinDLL('YahooAPIWrapper.dll')
      ctor = lib['YahooAPIWrapper_New']
      ctor.restype = ctypes.c_void_p
      get_bid = lib['YahooAPIWrapper_GetBid']
      get_bid.restype = ctypes.c_double
      
      wrapper = ctor()
      
      bid = get_bid(wrapper, ctypes.c_char_p("GOOG"))
      

      But I’ve tested it and the constructor fails when allocating the private part:

      _private = new YahooAPIWrapperPrivate();
      

      So you could test it and see if you have the same behavior or if it works on your side.

      But maybe you’re not using ctypes, if so could you elaborate more on your process?

      Thanks

    • Ok I’ve tested more thoroughly and think I’ve found the issue.
      This is related to .Net assemblies probing.
      I have a fix and will post this ASAP.
      Stay tuned! 🙂

  5. Hi,
    Thank you for the post. Can this technique be applied if I want to pop up a Window Form written in C# on .NET framework in legacy native C++ ?

    • Hi Tran,
      yes you can use whatever part of .Net you want, even some WPF. 😉
      The only thing you have to do is bridging the native code and the .Net code with the kind of plumbing described in this article.
      Let me know if you have any issue…

  6. Hi,
    First, thanks for your post.
    Also, do you know if it is possible to pass to a C++ function, a C# object as a parameter ? I mean in your example, lets take private static double ParseDouble(string value) function, you use a c# string as a parameter and I wanted to know if it is possible to pass a C# object like private static double ParseDouble(Object value) and interop with it in C++ dll.

    • Hi Romain,
      yes it’s possible but is more or less complex depending on what you intend to do.
      If you want to pass a structure things are relatively straightforward: http://msdn.microsoft.com/en-us/library/awbckfbz.aspx
      If you want to invoke methods then you’ll have to write a C++/CLI wrapper around your C# class, it will forward the calls from the native C++ side to the managed side.
      Hope this helps…

      • Actually I was thinking to use IntPtr and Marshal.GetNativeVariantForObject() to pass a pointer to the C++ library but I have to test. Do you think that is possible ?

        Anyway thanks for help and links.

        • IMHO it won’t move the needle a lot, and even if you can make it works it will be far more intrusive than building a wrapper that will cleanly uncouple the two parts.
          If you have a recurrent need for this kind of interop scenario you should seriously consider using SWIG to generate the plumbing.

          • Ok thanks for information.
            And a last question, did you know how to use c# enum type in a C++ unmanaged function ?

          • The simplest thing you can do is to redefine the enum on the native C++ side.
            This way you can transparently pass the enum values.
            You only need to take care to keep the two enum definitions in sync.

  7. But how you pass the value as a parameter ?
    For example :
    C# :
    public enum A
    {
    VALUE_1 =0,
    VALUE_2,
    VALUE_3
    }
    and i have a function like that : void function_A(A eValue);

    So if i understood , I have to do the same structure on the C++ side like that :
    enum A
    {
    VALUE_1 = 0,
    VALUE_2,
    VALUE_3
    };
    But how can I call the function function_A ? I mean how i can use the gcnew directive in order to pass the enum ?

    • If you’re using DllImport you can declare the function this way:

      [DllImport("MyDll.dll", EntryPoint = "function_A")]
      public static extern void FunctionA(A a);
      • Ok thanks for the tips.
        Anither question concerning the way to pass the parameters between the wrapper and the managed application ; when you do _private->yahooAPI->GetBid(gcnew System::String(symbol)); I think “symbol” is passed by value the a copy is done. If I use “ref” in the c# application, do you think when I call the function by the C++ application, the parameter will be passed by reference (no copy)?

        • symbol is passed by copy of reference.
          If you want to pass by reference of reference you can declare the symbol parameter as ref on the C# side.
          Here is a minimal example:
          A.cs:

          public class A
          {
              public static void ByCopyOfReference(string s)
              {
                  s = "pwned";
              }
          	
              public static void ByReferenceOfReference(ref string s)
              {
                  s = "pwned";
              }
          }
          

          test.cpp:

          #using "A.dll"
          
          int main()
          {
              System::String^ s = "ok";
          
              System::Console::WriteLine(s);
          	
              A::ByCopyOfReference(s);
          	
              System::Console::WriteLine(s);
          	
              A::ByReferenceOfReference(s);
          	
              System::Console::WriteLine(s);
          }
          

          Output:

          ok
          ok
          pwned
          
  8. Thank you for this post,
    Let me try to explain what I need: I have a large project written in c++ that I would like to leave untouched. I want to replace the current, functional Win32 user interface with a new WPF module I started implementing.
    I would like to encapsulate the WPF part and interact with it using SendMessage functions. I can probably write the wrapper as a Win32 window DLL to solve this. However, I wander how I can deal with the events from the WPF part. Sould I write the handlers inside the wrapper?
    Thank you in advance.
    Shaul Eizikovich

    • Hi Shaul,

      First, to develop your WPF UI you should use C#, don’t be tempted by developing your WPF UI in C++/CLI even if you are fluent in C++, for at least 2 reasons:
      – limited WPF integration in Visual Studio (e.g. no designer support)
      – a far smaller C++/CLI developer community and believe me WPF already comes with its own set of issues 🙂

      Secondly you should clearly isolate the Win32 UI layer from the “business” layer and have a self-contained business project with no dependency on the UI.

      Once you have a well designed native application remains the wrapping part.
      The best way of tackling this depends on the number of entry-points of the C++ business layer.
      If you have few entry-points:
      – not object oriented: simply build a static C# wrapper that uses DllImports
      – object-oriented: write a small C++/CLI wrapper
      If you have more entry-points and specifically object-oriented then you should use SWIG which will produce a C# wrapper automatically.

      Once you have a wrapper the communication between the two layers should be quite obvious, you simply use the wrapper from the WPF application in a transparent manner, something like:

      OneOfYourNativeClassesWrapper wrapper = ...;
      
      void Button1_Click(object sender, RoutedEventArgs args)
      {
      	outputTextBlock.Text = wrapper.ComputeValue(inputBox.Value);
      }
      

      Hope this helps…

      • Thank you pragmateek for your comprehensive reply.
        Thinking over and over again about the project I see it now as much simpler one:
        1. As you say, WPF window will be done as pure C# project using Visual Studio. I compile it as DLL.
        (Q. Can one C# DLL contain all my WPF windows or do I have to create a DLL per-window?)
        2. Around the WPF windows (that is, one or more DLLs) I write a C++/CLI wrapper along the lines you suggested. The wrapper does not have to be Object Oriented, so I could write it in C# as you suggested but I’m much more fluent with C++.
        3. The wrapper contains a hidden Win32 window to serve as target to application’s messages.
        4. The wrapper will be compiled as DLL with two interface functions: A constructor and GetWindowHandle that will return a handle to the hidden window.
        5. The wrapper will handle all events from the WPF windows.

        • 1) The WPF part is typically a full-fledged application, like was your Win32 application, not just a DLL.
          This application will contain the main entry-point and all the stuff related to the UI, including all your windows.
          Of course you can isolate the entry-point, the managed Main, in another project but it’s often useless if your windows are only used from this main.
          2) If your functional API is not object oriented and not too big (because you really don’t want to do all the marshalling yourself) you can indeed use DllImports, something like:

          class NativeInterfaceWrapper
          {
          	[DllImport("my_native_dll.dll", EntryPoint = "start_process")]
          	public extern static int StartProcess(int a, double b, string c);
          	
          	[DllImport("my_native_dll.dll", EntryPoint = "stop_process")]
          	public extern static int StopProcess(int id);
          	
          	[DllImport("my_native_dll.dll", EntryPoint = "compute_value")]
          	public extern static double ComputeValue(int n);
          }
          

          3) 4) 5) Why do you want to use window message passing between your WPF UI and your native layer?
          I’m obviously missing something but the WPF UI should handle events like clicks on buttons and in response interact with the legacy code through the wrapper to compute values for example.

          I don’t know what’s your exact use-case but typically here is the workflow:
          – the user starts the application exe file which starts the UI immediately, starting the WPF message loop (like the Win32 message loop) on the main thread
          – the WPF interface displays some inputs and some action buttons
          – the user fills in the inputs and clicks an action button
          – the button click event’s handler reads the input and calls a method of the wrapper and it gets some new values in return
          – it displays these new values on the interface.

          This assume that you have implemented a strict separation of concerns in your application: as an example a “business” method like “compute_value” should not interact with the UI, be it to read or write data.

          • I think this is simpler to have the managed part of your application, i.e. the WPF interface, to be the “master” part, i.e. the one that will drive things.
            You could do the reverse, i.e. driving your managed C#/WPF from native C++, using the technique demonstrated in this article, but this is really not the easy way. 🙂

          • I really appreciate your help. This is an impressive manifestation of good will!

            My current project holds a large C++ executable where the UI is only one, relatively small, module. I chose to implement the CU (Control Unit) of the executable as an invisible Win32 window so that it will serve as a hub to messages from the other units, including the UI.
            The UI (Currently implemented as another Win32 window) interacts with the CU through messages. I think it is a good way to separate units and to enable development of units in parallel. Anyway, this is what we’ve got.
            When The application starts, it creates the modules one by one, including the UI module.
            It is of course possible to reverse the order so that the UI starts the application, leaving the CU outside as a DLL or rewriting it in C++ (Compiling it with /clr is impossible since it contains and ). However, I don’t think it will be wise, especially not being a C# person.

            So I tried to create a C++/CLI wrapper to my (preliminary) WPF interface and the call the wrapper constructor from a plain C++ main. This failed. I suspect that this is because I didn’t declare my main thread as STA. I probably have to do it from the wrapper, calling the WPF in a new thread. No idea as how to do it. Wish me luck.

            Shaul

          • Ah OK I better understand your architecture.
            Isolating the modules this way and communicating through messaging is indeed a good design with full uncoupling.

            To run your WPF UI in another thread you can explicitly set the apartment-state with something like:

            void RunWPFMessageLoopOnWindow()
            {
            	Application WPFApp = new Application();
            	
            	WPFApp.Run(mainWindow);
            }
            ...
            Thread UIThread = new Thread(RunWPFMessageLoopOnWindow);
            UIThread.SetApartmentState(ApartmentState.STA);
            UIThread.Start();
            

            To send message from your WPF UI to your hub you can DllImport the SendMessage function.
            Here is the signature to use from the C# side : http://www.pinvoke.net/default.aspx/user32/SendMessage.html

            And to read messages sent by the legacy native part you can check this : http://stackoverflow.com/questions/624367/how-to-handle-wndproc-messages-in-wpf

  9. I’m almost there. Only annoying problem with WPF binding.
    My Win32 app opens a Win32 window which opens a WPF window.
    Moving the WPF window around sends it coordinates to the application and the topmost window.
    When I send a message to the Win32 window it processes it and calls (using your method) a method at the C# code-behind of the WPF window.
    So far so good.
    Here’s the problem: Since this method is not a WPF event handler it cannot effect the WPF user interface.
    Here’s the entire code-behind file (My method is Set_YYY()), “EventModel” is public class EventModel : INotifyPropertyChanged

    Could you give me a hint? Thank you!

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Data;

    namespace DatabindingExample
    {
    public partial class MainPage : Window
    {
    private EventModel _event;

    public MainPage()
    {
    InitializeComponent();

    // create a model object
    _event = new EventModel()
    {
    Date = new DateTime(2011, 7, 1),
    Title = “Silverlight User Group”
    };

    // bind the Date to the UI
    this.DataContext = _event;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
    _event.Title = _event.Title.ToLower();
    _event.Date = _event.Date.AddDays(1);
    }

    public void Set_YYY()
    {
    _event.Title = _event.Title.ToUpper();
    }

    }
    }
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    • If you need to dispatch the call to the UI thread you can use its dispatcher, something like:

      public void Set_YYY()
      {
          this.Dispatcher.Invoke(() => { _event.Title = _event.Title.ToUpper(); });
      }
      
  10. This did not work but hey, thank you for the general direction.
    Amazing how they made WPF complicated to anyone using it differently from the orthodox way.

    • What’s the error you get?
      WPF is a framework so you have to stick with its design, otherwise yes things can quickly become complicated. 🙂
      WPF is not the best tool for everything UI related, but 90% of the time it’s better than the alternatives like Winforms.

  11. It does not compile. It says: error CS1660: Cannot convert lambda expression to type ‘System.Delegate’ because it is not a delegate type

    Actually the alternative I was thinking of was Direct2D. It is pure Win32 replacement for DGI/GDI+ , it has fantastic performance but it does not support ‘controls’ natively.
    You can write your own controls (I did create buttons) though.

    I chose WPF because it enables you to design non-standard GUI using XAML – I hope I over come this last (hurdle) and continue with the actual development.

    • Ah OK, you’re not using the latest version.
      This should do the trick:

      this.Dispatcher.Invoke((Action)(() => { _event.Title = _event.Title.ToUpper(); }));
      

      The reason is that without more information the C# compiler does not know to which delegate type it should map the lambda.
      In the latest version of .Net there is an overload of Invoke that takes an Action so you don’t need to cast yourself, the compiler will use the correct overload.

      Believe me WPF is the way to go, “there is no alternative” 😉

      • Dear pragmateek,
        The last solution compile but did not affect the UI. I stepped into it with the debugger and it did seem to do everything it should only that the textbox was not affected.
        HOWEVER, I did solve the problem in a different way that has one great advantaged: It works.
        You might be interested to add it to this fantastic page.
        I followed this “Walkthrough” by MS: http://msdn.microsoft.com/en-us/library/ms744829(v=vs.100).aspx#communicating_with_the_page
        Search for this interesting paragraph:
        The simplest solution to this issue is to implement a managed class that contains a set of static fields to hold references to any managed objects that you need access to. The sample uses the WPFPageHost class to hold a reference to the WPF content, plus the initial values of a number of its properties that might be changed later by the user. This is defined in the header.
        And it is simple. You create a STATIC class in the wrapper and save there a reference to your page and controls.
        You can later use them as simple pointers and write data directly to the controls!
        Hope you like it and THANK YOU for your help!

        • Glad you make it work! 🙂
          Not sure it’s a very orthodox solution but I guess it’s a pragmatic choice and you can’t be blamed for that. 😉

  12. Hi,
    thank you for all the information in the post.
    I have implemented your example to use it with VS2010 and it is working just fine.
    But I have a question concerning deconstructors in this example and it would be great if you can help me with that. I am wondering why the deconstructor is never called. Also, I do get a “Detected memory leaks!” information in the output when using “_CrtDumpMemoryLeaks();” with the YahooTest.cpp which referes to _private. For example:

    yahoo {_private=0x009f5320 } YahooAPIWrapper
    _private 0x009f5320 YahooAPIWrapperPrivate *

    Detected memory leaks!
    Dumping objects ->
    {144} normal block at 0x009F5320, 4 bytes long.

    This happens even with a very short test program:

    #include “stdafx.h”
    #include “YahooAPIWrapper.h”
    #define _CRTDBG_MAP_ALLOC
    #include
    #include

    int main()
    {
    YahooAPIWrapper yahoo;
    _CrtDumpMemoryLeaks();
    }

  13. I solved the memory leakage problem by declaring the destructor in the YahooAPIWrapper.h as follows:

    public: ~YahooAPIWrapper();

    With the CRT Debug Library it depends where you put the _CrtDumpMemoryLeaks(). I verified it now by using the Visual Leak Detector (http://vld.codeplex.com/) which shows me the complete callstack if memory allocation has led to a leak.

    With declaring the constructor in the wrapper header file I get: “No memory leaks detected.”

    So thank you again for your excellent overview of how to write a wrapper. 🙂

    • Hi Martin,

      good catch: the header is not up to date!
      The version I have on my computer correctly includes the destructor declaration. :/
      I’ll fix that.

      Moreover note that any “destructor” (aka finalizer) you define in the C# part should be called too:

      public class YahooAPI
      {
          ...
      	
          ~YahooAPI()
          {
      	Console.WriteLine("YahooAPI.~YahooAPI");
          }
      }
      

      Thanks for the catch. 🙂

    • Thanks Steve for your comment.
      Glad this article was useful to you.

      Could you please share more (non confidential) information about your use case?

      Thanks. 🙂

  14. The “.lib” file generated by Visual Studio for C++/CLI wrapper cannot be linked statically in XE4’s C++ project (perhaps different compilers). It gives some kind of COFF linking errors.
    If we need to load this Wrapper DLL dynamically in C++ code in XE4 then how can we expose the class and its member functions including the functions that create and destroy the object for this Class exposed via wrapper C++/CLI dll?
    Can you provide a sample interface header for such a scenario when we need to expose and use this wrapper for C++ code in XE4.

    Thanks,
    Santosh

    • Hum, first it surprises me that they don’t support this scenario.
      You should really contact their technical staff to be sure.

      And if it really is not possible then you can use a C interface which should create no issue as there is no specific mangling rules.

      You can have a look at this article: http://pragmateek.com/if-your-plumbing-doesnt-work-youre-just-not-using-enough-pipes/
      Note that you don’t need the C++/CLI wrapper anymore if you use a C interface.
      Don’t put the C interface above the C++/CLI interface, what I’ve demonstrated in the “If your plumbing doesn’t work you’re just not using enough pipes”, because in your case you just don’t need it.

      Basically you will create a new mangling rule but one that you control to be independent of the compilers.
      If you have no overloads it will be quite simple; if you have some overloads then you’ll have to decide how you distinguish them: by appending an index (DoSomething_1, DoSomething_2, …), by appending the parameters’ types (DoSomethingWith_int, DoSomethingWith_double, …) or in any other readable manner.

  15. Hi Pragmateek,

    My scenario is almost similar to above Post,except following
    My App (XE4 C++ code) -Loads- C++/CLI Wrapper code (Visual Studio 2012) talks to .NET C# DLL (Visual Studio 2012)

    Approach mentioned by you looks simple and easy to follow
    but I’m struggling to expose the Class or its objects to my Native XE4 C++ App.

    I’m trying to Load my C++/CLI DLL in my XE4 C++ code using LoadLibrary() and then I needed access to Class and its public
    functions which I believe should be made available as we have declared it as
    “class __declspec(dllexport) WrapperClass”

    but how do I get to the object of this class in my Native XE4 C++ code.
    I saw you mentioned something like follows which I declared in my Wrapper DLL somewhat like following:
    —————————————————————–
    __declspec(dllexport) Wrapper *CreateObject()
    {
    return new Wrapper();
    }
    __declspec(dllexport) void DestroyObject(Wrapper *instance)
    {
    delete instance;
    }
    —————————————————————–

    I’m particularly struggling with exposing of C++/CLI DLL Class, its methods and its object to my XE4 C++ DLL to be used in XE4 code. Can you please help with some sample code?

    Would appreciate your kind help.

    Thanks

    • Hi Santosh,

      I don’t know XE4 but the C++/CLI library can be used just like you
      would with a pure native C++ library.
      And this is a two steps process:
      – at compile time you write your code basing it on the C++ library
      headers, you trust them to match existing members of the library
      – at link time the linker will try to find the symbols you’ve used in
      the library.
      To know which symbols are exported you can run “dumpbin /exports
      CppCliWrapper.dll” and you should see mangled class’ members names.

      There is nothing specific to C++/CLI: the CppCliWrapper.dll library
      has the same interface than any native C++ library.
      The only possible issue I imagine is different mangling rules between
      the CL compiler and the XE4 C++ code.
      Indeed each compiler has often its own mangling rules.

      So your issue is how to use ANY native C++ library from XE4 code, and
      to this I have no answer but I’m sure the community forums or users
      support of the vendor have the answer. 🙂

      But I’m quite optimistic as chances are good they have anticipated
      this kind of common needs and allowed interoperability with CL
      generated C++ code.

      Hope this helps, and if you have more specific questions do not hesitate to ask.

      Please tell me when your issue is fixed.

      Thanks.

      • Hi Pragmateek,
        Thanks for your reply. I could move forward by Fixing all the bits and pieces where I was initially struggling with my current scenario:
        My App (XE4 C++ code) -Loads- C++/CLI Wrapper code (Visual Studio 2012) talks to .NET C# DLL (Visual Studio 2012)

        One specific thing now that I need some help with is how to Pass a parameter by Reference across Native C++ Code to C++/CLI Wrapper code (Visual Studio 2012).
        Following is an example of one of my Exposed function via Warpper DLL.
        DLLEXPORT int ProcessSingleRequest(void* wrapper, const char *request, char *response)
        {
        return reinterpret_cast(wrapper)->ProcessSingleRequest(request, response);
        }

        In my Wrapper class implementation of ProcessSingleRequest() I could manage to get “response” changed to the desired value that I want to return but when it returns from above exported “C” interface its reset to NULL or undefined value. What am I missing here?

        My code is based on your article shared at “http://pragmateek.com/if-your-plumbing-doesnt-work-youre-just-not-using-enough-pipes/”

        Hope to hear from you soon…

        • Hi Santosh,

          could you provide a minimal sample that shows the issue?
          But I think you should use a char** instead of a char*, because you’ll have to update the value of the pointer.

          Thanks

  16. I’m very new to C++/CLI and I use Visual Studio (2008) rather occasionally.
    But I have a job to do, so I thought your article was a godsend.
    However:
    If I use Visual Studio instead of command-line compiling, the wizard automatically provides namespaces when it creates a project. I’m rather surprised to see there are none in your example. I hope adding some is not going to be a problem.

    I must have a completely wrong idea about what C++/CLI is about but
    I’m hugely surprised to see the class keyword appear in the C++/CLI wrapper CPP file. I thought that was left to the header file in C++!
    In any case I’m getting a compiler error when I try to compile a project named YahooAPIWrapper (which is defined as a library).
    \YahooAPIWrapper.cpp(17) : error C2011: ‘YahooAPIWrapper’ : ‘class’ type redefinition

    • Hi Henri,
      – Namespaces are only a tool to organize types so using one should not change anything.
      I’ve ommited namespaces to keep things as simple as possible.
      – Concerning the class, AFAIK in native C++ too you can both declare and define a class in the same CPP file.
      Nevertheless it’s indeed cleaner to declare the class in the header file and define its members in the CPP file.
      As for your error it’s probably due to a mix between this two approaches, so sticking with the best-practice you mention, i.e. declaring in the header, and including it wherever you use YahooAPIWrapper, and defining in the CPP should fix the issue.
      Moreover you may need to guard against recursive inclusion of the header with a “#pragma once”.
      Hope this helps. 🙂

  17. Your article is the clearest I’ve seen on this subject, so thanks for that! I’ve compiled your source as three projects in one solution in VS 2010. It all compiled without error. When I debug, it blows up with:

    Unhandled exception at 0x767ec41f in yahoo_look.exe: 0xE0434352: 0xe0434352.

    on the line:

    YahooAPIWrapper yahoo;

    That’s in the main console .EXE. Clearly, something is compiled incorrectly, but I don’t know what. Where can I begin looking? Thanks for your help!

    • Hi Donald,
      this is strange, this line will simply allocate the wrapper and call its constructor which does not do crazy things.
      So try to debug the YahooAPIWrapper constructor to identify which instruction is responsible for this error.
      Thanks.

  18. I added a reference to YahooAPI from YahooAPIWrapper. The compiler says the reference is already there, but now it works! Great!!! Thanks for a very useful project.

    Is there any easy way to debug into the C# routine from unmanaged, or do you just use message boxes or file probes?

    • Glad it works. 🙂
      Visual Studio should be smart enough to allow debugging both managed and unmanaged code.
      I don’t remember if there was a special configuration or if you needed to attach the debugger afterward or use another trick.
      This documentation may help you: http://msdn.microsoft.com/en-us/library/kbaht4dh.aspx (the setting makes sense and this is simpler than in my memory :)).

    • Donald,
      When you say “I added a reference to YahooAPI from YahooAPIWrapper.” what exactly did you do. I’ve built my own 3 components, all compile and execute but like you when I execute
      YuniqueAPIWrapper yunique;

      I crash never getting to any break point, if I trace with assembly it gets buried to deep for me to follow. I should add that my test app is an MFC Dialog type app as that is what the final app will be.

      many thanks

    • I just added a console test app and it does the same thing. For configurations my test apps and the wrapper are defined as WIN32 and the C# is x86. I added a reference in the C# app to the wrapper DLL which makes no sense to me and it had no effect.

      Any ideas?? anyone??

      • Seems like the CLR can’t load, so probably an issue with bitness.
        I fear Win32 is misleading and can also generate x64 code, which is probably the case if you are on a x64 platform.
        To check this you can use the dumpbin tool:

        dumpbin /headers your_binary_component

        And look for “machine (x86)” or “machine (x64)”.

        • OK, I got it, the C# dll was in the wrong folder so the system could not find it. These multi project solutions are sometime a PITA to setup.

          Thanks again for your code sample it’s been a great help.

    • Hi Donald,
      I am getting the same exception at the same line. The app is compiled as win32 console application. Can you please tell me where have you added the reference, what change did you made exactly?

  19. The sample is working fine when the app is compiled as a console app. When I compile the app as a .DLL and call it from another routine, it blows up on this line, with an Invalid Access error deep in Windows:

    #include

    #include “YahooAPIWrapper.h”

    int main()
    {
    const char* stock = “GOOG”;
    YahooAPIWrapper yahoo; // <— blows up here.

    double bid = yahoo.GetBid(stock);
    double ask = yahoo.GetAsk(stock);

    There's no material difference in the code, and the YahooAPIWrapper.cpp and YahooAPI.cs are not changed at all. All code compiled with no errors, and the .DLL loads and runs up to the line that blows up. When I put it back to console, it again works fine. It's too simple to be anything very serious, but I sure can't figure this out. Thanks for your help!

    • Hum, strange indeed.
      Is the YahooAPIWrapper constructor called?
      If yes can you identify which line exactly is crashing the app inside it?
      And what happens if you instead allocate the wrapper on the heap: YahooAPIWrapper* yahoo = new YahooAPIWrapper();?

  20. I don’t know if the constructor is called. I tried to set breakpoints in that part of the code, but couldn’t break there. Yes, I tried allocating on the heap, but the result was the same.

    • If you can’t break you can always use some good old print statements to be sure. 🙂
      Could you please send me a minimal project that illustrates the issue, I’ll check it.
      Thanks.

  21. Well, it’s working now. I created two projects, one console, one dll. They both worked! I copied the .dlls to my actual app, and the blowup was the same as before. In my app, the .exe calls through 3 levels of .dlls to get to your test code. When I compiled ONLY the .exe in release mode, it worked (no blowup). I haven’t pinpointed the difference between debug and release for the .exe, but it works now! Don’t know how that could possibly relate to .dlls way downstream… Progress, maybe. Thanks for your help!

    • Seems like a memory issue indeed, but why does it appear when creating the class…
      I really don’t like this kind of situation where you lose control, and things are kind of magic.
      At least it forces us to be humble because we know we can’t control and understand everything. 🙂
      I only hope the issue is not in my implementation though it’s pretty basic…

  22. First off, thank you for writing this. Excellent stuff!

    I have the need to call some vb.net dlls from an unmanaged C++ app. Though I see the *fun* in writing the wrapper class by hand, I do have to deal with deadlines 🙂 You mentioned that swig automates this plumbing step. Can you eloborate on this? As far as I can tell, swig only works with C/C++ header files. How do you get it to plumb managed vb or c# code?

    • Hi and thanks for your comment.

      Concerning SWIG you’re right it is not a good fit for your use-case.

      Do you really need to export all the types of the VB.Net library?
      You should enumerate the “services” you will need from the library and only expose entry-points for them, which should considerably reduce the development effort.
      Note that you could develop these high-level services with C# which interoperates seamlessly with VB.Net.
      C# is a better long-term choice than VB.Net and easier to understand if you are a C++ developer.

      If you really need to use the entire object model then your best bet is probably COM interop which is supported by Visual C++.

      Could you tell us more about the role of this VB.Net library, and which functions you’d like to leverage from the native C++ side?
      Because depending on them there is plenty of more specific solutions.

      Thanks.

      • Hey, thanks for the quick reply!

        Short history: We have 2 vendor apps. One is .Net based and the support/development team chose to use vb.net at the time (~2006, they were mostly vb6 guys anyway). That has been the defacto language since (I’ll leave the politics out as to why they won’t move to C#). The other app is C++ based with far fewer developers. I would like to take advantage of all the helper classes (oracle wrappers, application interface wrappers, custom sql queueing, etc) that have been developed using vb.net instead of reimplementing them in C++. Exposing them via COM is the normal mode, but we have several processes that require a lot interactive interactions (sql queries, etc) and the COM interop layer slows that process down a bit. I’d like to compare the performance between COM and C++/CLI.

        Ah, I just re-read your section regarding swig. You were talking about managed to unmanaged plumbing, doh!

        While I’m tinkering with creating this wrapper class, how do I handle dll’s with multiple classes defined? For example, I have a project called MyAccess and it’s build time artifact is called MyAccess.dll. Within that project, there are 3 classes: MyConnection, MyReader and MyAttribute. I’ve tried to follow your example, but I’m getting compile errors.


        #using "MyAccess.dll"
        #include
        using namespace System::Runtime::InteropServices; // Marshal

        class MyAccessWrapperPrivate
        {
        public: msclr::auto_gcroot myConnection;
        };

        class __declspec(dllexport) MyAccessWrapper
        {
        private: MyAccessWrapperPrivate* _private;

        public: MyAccessWrapper()
        {
        _private = new MyAccessWrapperPrivate();
        _private->myConnection = gcnew MyConnection();
        }
        }

        Errors:

        C:\devel\>cl /clr /LD MyConnectionWrapper.cpp
        Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01
        for Microsoft (R) .NET Framework version 4.00.30319.1001
        Copyright (C) Microsoft Corporation. All rights reserved.

        MyConnectionWrapper.cpp
        MyConnectionWrapper.cpp(12) : error C2065: 'MyConnection' : undeclared identifier
        MyConnectionWrapper.cpp(12) : error C2059: syntax error : '>'
        MyConnectionWrapper.cpp(13) : error C2143: syntax error : missing ';' before '}'
        MyConnectionWrapper.cpp(16) : error C2143: syntax error : missing ';' before '{'
        MyConnectionWrapper.cpp(20) : error C2143: syntax error : missing ';' before '{'
        MyConnectionWrapper.cpp(23) : error C2143: syntax error : missing ';' before '}'
        MyConnectionWrapper.cpp(24) : error C2143: syntax error : missing ';' before '}'
        MyConnectionWrapper.cpp(25) : error C2143: syntax error : missing ';' before '}'
        MyConnectionWrapper.cpp(25) : fatal error C1004: unexpected end-of-file found

        Hopefully the code tag worked.

        Thanks!

        • Your use-case is indeed interesting.

          As for the COM performance issue, if you are I/O-bound, like interacting with a database or using the FS then the overhead should be negligible.

          COM is not a good fit if you have a lot of short interactions.
          e.g. to take an extreme example:

          for (int i = 0; i < aReallyBigNumber; ++i)
          {
              myCOMObject.Increment(someDataToMarshal);
          }
          

          As for the issue you have with the wrapper I think that classes in your assembly are in namespaces so you must import them in the current scope:

          using namespace MyAccess::Database::Oracle;
          

          You should then be able to access the MyConnection class.

          • It’s more iterative and makes *a lot* of calls.

            Regarding namespaces, I don’t see any explicit namespaces declared on the vb side. If I use the following code:
            #using "MyAccess.dll"
            #include
            using namespace System::Runtime::InteropServices; // Marshal
            using namespace MyAccess;

            class MyAccessWrapperPrivate
            {
            public: msclr::auto_gcroot myConnection;
            };

            class __declspec(dllexport) MyAccessWrapper
            {
            private: MyAccessWrapperPrivate* _private;

            public: MyAccessWrapper()
            {
            _private = new MyAccessWrapperPrivate();
            _private->myConnection = gcnew MyConnection();
            }
            }

            I get this from the compiler:

            MyConnectionWrapper.cpp
            MyConnectionWrapper.cpp(20) : error C3767: 'MyAccess::MyConnection::MyConnection': candidate function(s) not accessible

  23. If there is no namespace as I’ve did then indeed you dont need any using namespace.

    Is the MyConnection class public?

    By default classes without any qualifier are internals, i.e. they can only be accessed from the same assembly.

  24. Thanks for this great article! It is very very helpful. I am trying to write a windbg extension(c++ dll) which needs to take advantage of some Thirdparty C# program. I learned the way you did, got a demo work. But also run into some problem. I tried to change the return type as string instead of const char*, got the crash in the windbg UI, maybe it is because the STL compatible issue as you mentioned?
    “moreover you may wonder why we use “const char*” instead of “std::string“: because publicly exposing STL types is brittle as their implementation could differ from vendor to vendor and even between different versions from the same vendor”.

    I also plan to return some STL containers like vector, map. Do you have any workarounds? Do we have to stick to the primitive data types? Or we can send the container ref as an argument. I am just thinking about it, haven’t tested it yet.

    • Hi Stanley,

      thanks for your kind feedback.

      And yes I can confirm that exposing STL types is definitely a dangerous practice that can cause a number of unexpected behaviors; but not sure the issue you have is one of them.

      AFAIK there is no plug-and-play workaround but if you want to control your public API you can create some alternatives for the types you intend to use, that are safe to transfer across the API boundaries.

      For strings using char * is a standard practice, as well as using arrays instead of vectors.
      For the map you could create a class with two arrays: one with the keys, another with the values, or represent it as an array of key-value pairs.
      Either use a known convention if you can find one or the simplest implementation for your special case, so that on the calling side converting between them and standard C++ types is easy.

      • Thank you for the advice. I tried to pass by reference, and this time I found it retrieved nothing instead of crashing. So I guess it might be some memory issue. But both ways work correctly in an exe I wrote for test. I am still shooting in the dark. I guess maybe my extension is based on COM that’s why it happens. I don’t know the internal mechanism. My assumption is based on that’s the only difference I know between the extension dll and the my test exe.

        • If you throw COM into the equation you’re really asking for troubles. 😉
          More seriously if you are well versed in COM you may try to expose what you want from the .Net/C# stuff via COM, as it is a “standard” platform with, AFAIK, well defined types.

          • Makes sense. Actually i gave up both. As I found the C# exe needs the app.config at runtime to do the basicbinding. It probably would take another amount of time to get around it. I switched to python. Now the feature is done. Though I am not able to make interop work. It is a good experience. Thanks again!

  25. Thanks for your feedback Stanley.
    Python is definitely a magic tool.
    I’m always amazed of this kind of “success stories” : can’t do it with C++/Java/C#… done it with Python.
    I hope one day I’ll have a closer look at this strange creature. 🙂

  26. Hi pragmateek,

    when I’ll compile:
    #using “YahooAPI.dll”
    // or #using “..\CS\bin\Debug\YahooAPI.dll”
    // or #using “C:\Projekte\CPP CS Wrapper\CS\bin\Debug\YahooAPI.dll”

    #include “stdafx.h”
    #include

    using namespace System::Runtime::InteropServices; // Marshal

    class YahooAPIWrapperPrivate
    {
    public: msclr::auto_gcroot yahooAPI;
    };

    the compiler says: “error C2065: ‘YahooAPI’: undeclared identifier”.

    But syntax highlightning shows that YahooAPI is known and the object catalogue shows the dll with the class YahooAPI also.

    Thanx Volker

    • Hi Volker,

      I guess the YahooAPI managed project correctly generates the YahooAPI.dll assembly…
      Have you tried to put this assembly in the same folder as your C++/CLI wrapper source file?
      If it’s still broken in VS then try to compile using the command line, this is the safest way to check if there is a “true” issue or if this is just some VS glitch.

      • Hi pragmateek,
        thank you for your great web-site and helping.
        I’ve found my mistake: it’s necessary to #include “stdafx.h” before #using “YahooAPI.dll”.
        Incidentally #1: in your ZIP, there is no destructor of ~YahooAPIWrapper.
        Incidentally #2: I’ve done a small improvement in YahooAPIWrapper.h:
        #ifdef DLL
        #define DLLEXP __declspec(dllexport)
        #else
        #define DLLEXP
        #endif
        class DLLEXP YahooAPIWrapper
        {…}
        So I can include YahooAPIWrapper.h in YahooAPIWrapper.cpp (where I set the define DLL) and in test.cpp. So I’ve only ONE definition of the class YahooAPIWrapper in YahooAPIWrapper.h and not a second definition in YahooAPIWrapper.cpp.

        ciao
        Volker

        • Hi Volker,

          glad you’ve fixed your issue. 🙂

          Thanks for your feedback and the catches.
          The destructor issue was fixed some months ago, as you can see in the article but for some reason the ZIP was not up-to-date. :/
          This is now fixed.

          As for the other improvement, yes this is not best of breed C++ 😉
          I’ll fix it when I have more time to thoroughly test it.

          All the best. 🙂

  27. Works perfect from C++. Can I use this wrapper from Delphi? If so, then how? Just calling external library gives an error “entry point not found”. Dllexportviewer shows that export functions have quite strange names.
    Thanks!

    • Hi, glad it works for you.

      The strange names are the result of mangling which encodes the parameters metadata like types.

      For use from Delphi I think a direct binary communication might be complex, so you’d better try with COM interop if this is an object oriented API.

      If you have simple entry points (a la C, i.e. not OO) then you could try the DllExport extension: http://stackoverflow.com/a/6175291/145757.

    • The article you point to was more of a proof of concept, you should avoid using so many layers, this would be a nightmare to maintain.
      I think COM is your best bet because on the .Net side the COM interop layer is well implemented and using .Net components through COM, e.g. from VBA (check my other articles), is (almost) a breeze.
      To be sure this is the best choice you should ask Delphi experts but I’d be surprised if there was other serious alternatives…

  28. Can you please give an example of how to passing arrays as argument?
    I have an VC++ MFC program, and I want to call a function in c# dll like:
    int LoadCodes(out int numData, out long[] Bcols, out float[] Codes, out string[] Names, out string[] ShortNames). Can you give me some advice please? Thanks!

    • Hi Jin,

      here is a full sample for your use-case:
      – C# code to call:

      public int LoadCodes(out int numData, out long[] Bcols, out float[] Codes, out string[] Names, out string[] ShortNames)
      {
      	numData = 3;
      	
      	Bcols = new [] { 1l, 2l, 3l };
      	Codes = new [] { 1f, 2f, 3f };
      	Names = new [] { "One", "Two", "Three" };
      	ShortNames = new [] { "O", "Tw", "Th" };
      
      	return 0;
      }

      – C++/CLI wrapper code:

      int YahooAPIWrapper::LoadCodes(int* numData, long** Bcols, float** Codes, char*** Names, char*** ShortNames)
      {
      	int csNumData = 0;
      	cli::array^ csBcols = nullptr;
      	cli::array^ csCodes = nullptr;
      	cli::array^ csNames = nullptr;
      	cli::array^ csShortNames = nullptr;
      
      	int csReturnValue = _private->yahooAPI->LoadCodes(csNumData, csBcols, csCodes, csNames, csShortNames);
      	
      	*numData = csNumData;
      	
      	*Bcols = new long[csNumData];
      	
      	for (int i = 0; i < csNumData; ++i)
      	{
      		(*Bcols)[i] = csBcols[i];
      	}
      	
      	*Codes = new float[csNumData];
      	
      	for (int i = 0; i < csNumData; ++i)
      	{
      		(*Codes)[i] = csCodes[i];
      	}
      	
      	*Names = new char*[csNumData];
      	
      	for (int i = 0; i < csNumData; ++i)
      	{
      		(*Names)[i] = (char*)Marshal::StringToHGlobalAnsi(csNames[i]).ToPointer();
      	}
      	
      	*ShortNames = new char*[csNumData];
      	
      	for (int i = 0; i < csNumData; ++i)
      	{
      		(*ShortNames)[i] = (char*)Marshal::StringToHGlobalAnsi(csShortNames[i]).ToPointer();
      	}
      	
      	return csReturnValue;
      }

      - native C++ program code:

      int numData;
      long* Bcols;
      float* Codes;
      char** Names;
      char** ShortNames;
      
      int returnValue = yahoo.LoadCodes(&numData, &Bcols, &Codes, &Names, &ShortNames);
      
      std::cout < < "Return value: " << returnValue << std::endl;
      std::cout << "Num data: " << numData << std::endl;
      std::cout << "Bcols[0], Bcols[1], Bcols[2]: " << Bcols[0] << ", " << Bcols[1] << ", " << Bcols[2] << std::endl;
      std::cout << "Codes[0], Codes[1], Codes[2]: " << Codes[0] << ", " << Codes[1] << ", " << Codes[2] << std::endl;
      std::cout << "Names[0], Names[1], Names[2]: " << Names[0] << ", " << Names[1] << ", " << Names[2] << std::endl;
      std::cout << "ShortNames[0], ShortNames[1], ShortNames[2]: " << ShortNames[0] << ", " << ShortNames[1] << ", " << ShortNames[2] << std::endl;

      Hope this helps...

  29. This is a wonderful article and have been trying to add it to my attempt at wrapping the TFS API. I am still struggling a bit to manage even the connection. Hopefully I can get some suggestion or tips from you please.
    The idea is to use TFS API in a C++ (QT5) project.

    • Thanks for the feedback Vivian.
      I don’t know QT but as it is native C++ there should be no specific stuff.
      The C++/CLI wrapper is a pure native C++ component that should integrate seamlessly in your QT project.
      Which issue(s) do you have?

  30. New to all of this but I’m trying to setup a project via VS2013. Using the CLR Library project setup and attempting to define the header file I’m a bit perplexed on how to define the header. Would it be possible for someone to show the header file (YahooAPIWrapper.h) setup and I’ll try to go from there with the cpp.

    many thanks

    • Here is the header I’ve used:

      class YahooAPIWrapperPrivate;
      
      class __declspec(dllexport) YahooAPIWrapper
      {
          private: YahooAPIWrapperPrivate* _private;
      
          public: YahooAPIWrapper();
      	
      	public: ~YahooAPIWrapper();
          
          public: double GetBid(const char* symbol);
      
          public: double GetAsk(const char* symbol);
          
          public: const char* GetCapitalization(const char* symbol);
          
          public: const char** GetValues(const char* symbol, const char* fields);
      	
      	public: int LoadCodes(int* numData, long** Bcols, float** Codes, char*** Names, char*** ShortNames);
      };
    • OK, I got that to work

      #pragma once

      using namespace System;

      class YuniqueAPIWrapperPrivate;

      class YuniqueAPIWrapper
      {
      private: YuniqueAPIWrapper* _private;

      public: YuniqueAPIWrapper();
      public: ~YuniqueAPIWrapper();

      public: bool Connect();

      };

      but when I compile I get an error (class type redefinition) on this line:

      class __declspec(dllexport) YuniqueAPIWrapper

      #include “stdafx.h”

      #include “YuniqueAPIWrapper.h”

      #using “YuniqueAPI.dll”

      #include

      using namespace System::Runtime::InteropServices; // Marshal

      class YuniqueAPIWrapperPrivate
      {
      public: msclr::auto_gcroot yuniqueAPI;
      };

      class __declspec(dllexport) YuniqueAPIWrapper
      {

      what am I doing wrong?

      Many thanks

      • The issue is that you are defining the class both in the header and the implementation files.
        So drop the class YuniqueAPIWrapper redefinition and instead use:

        YuniqueAPIWrapper::YuniqueAPIWrapper()
        {
            ...
        }
    • Thanks for the reference Ryan.
      But I must be missing something as I don’t understand why there is an additional indirection layer…

      • There’s effectively the same number of indirection layers:
        Your .NET class YahooAPI corresponds with the green “C# Class” box (or class Calculator in his example)
        Your class YahooAPIWrapperPrivate corresponds with the red “IL Bridge” box (or class ILBridge_CppCliWrapper_Calculator in his example)
        Your class YahooAPIWrapper corresponds with the red “Native class” box (or class NativeExport_CppCliWrapper_Calculator in his example).

        The main difference is his ILBridge_CppCliWrapper_Calculator has the gcroot member
        private, not public, and so he has only simple wrapper functions in the NativeExport class rather than directly accessing the gcroot member from that class and having the actual code there too. I think this is a general question about how best to do PIMPL (e.g. http://www.gotw.ca/gotw/024.htm)
        Maybe an advantage of Sasha’s way is that you can ensure the NativeExport class is truly native only because you compile it with #pragma unmanaged?

        Using CLI to go the other direction (from C++ to .NET) doesn’t require the extra layer of indirection because C# doesn’t require #including a class declaration header file in the same way as in native C++ to use a class.

        It was helpful to have yours as a second example, with the discussion about auto_gcroot and design Q&As. Thanks.

  31. I got this exception running the final test.exe:

    Unhandled Exception: System.FormatException: Input string was not in a correct format.
    at System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
    at YahooInCSharp.YahooAPI.ParseDouble(String value)
    at YahooInCSharp.YahooAPI.GetBid(String symbol)
    at YahooAPIWrapper.GetBid(YahooAPIWrapper* , SByte* symbol)

    I got the same exception when attempting to call GetBid from a C# Main

  32. Hi Pragmateek,
    I’ve been reading your blog with great interest.
    I eventually need to solve a problem of a very similar nature, but am struggling with the C++ syntax. (It’s been several years, unfortunately)

    As a quick synopsis, I have a C# .dll that implements a client-server object network which itself satisfies a very stringent set of rules. basically,
    every object can be described as a set of (optionally read only) properties or methods
    return types are either primitives (e.g. string, boolean, int, float) or objects, or arrays of primitives or objects.
    parameters are either primitives or objects or arrays of primitives or objects.
    thrown exceptions are also objects from within the model.
    and finally, callers can create new objects from the model, or reuse existing ones.

    with this in mind, here’s a fairly small (3 classes) C# example describing the model.

    Duplicate.cs
    namespace ObjectNetwork
    {
    public class Duplicate : System.Exception
    {
    private String m_message;

    internal Duplicate(String m)
    {
    m_message = m;
    }
    }
    }

    Stock.cs
    namespace ObjectNetwork
    {
    public class Stock
    {
    private String m_name;
    private double m_value;
    public Stock(String name)
    {
    m_name = name;
    }

    public String Name
    {
    get
    {
    return m_name;
    }
    }

    public double Price
    {
    get
    {
    return m_value;
    }
    set
    {
    m_value = value;
    }

    }
    }
    }

    Basket.cs
    namespace ObjectNetwork
    {
    public class Basket
    {
    private ArrayList m_allStocks = new ArrayList();
    public Basket()
    {
    Stock a = new Stock(“A”);
    a.Price = 10;
    Stock b = new Stock(“B”);
    b.Price = 15;
    m_allStocks.Add(a);
    m_allStocks.Add(b);
    }

    public void AddStock(Stock s)
    {
    Stock[] ss = AllStocks;
    for (int i = 0; i < ss.Length; i++)
    if (ss[i].Name.Equals(s.Name))
    throw new Duplicate(s.Name + " is an existing stock in the basket");
    m_allStocks.Add(s);
    }

    public Stock[] AllStocks
    {
    get
    {
    return (Stock[])m_allStocks.ToArray();
    }
    }
    }
    }

    Can you give me an idea of what the generated C++/CLI interfaces and implementations will look like?
    Appreciate the help,
    Thanks
    Anil

    • Hi Anil,
      my C++ skills are rusty but here are some ideas for the native C++ side API:
      String -> char* (avoid std::string which is not safe across libraries boundaries)
      Stock -> Stock& or Stock*: s is a .Net reference, and equivalents in C++ are references and pointers
      Stock[] -> Stock**: in C++ we often use contiguous set of objects as arrays
      On the private implementation side:
      ArrayList (you’d better use the generic type List<Stock>) -> std::vector<Stock*>

  33. My real problem is that the ‘wrapper’ managed and un-managed h and .cpp files i created to emulate this object network aren’t compiling.
    I’m running into issue attempting to pass managed references around from one object to another.
    Ah well.
    Thanks
    Anil

    • Here is a full sample with your object model.
      First there is a bug in your C# code I’ve fixed:
      using System.Linq;
      ...
      public Stock[] AllStocks
      {
      get
      {
      return m_allStocks.Cast<Stock>().ToArray();
      }
      }

      Here is the C++/CLI wrapper:
      #using "ObjectNetwork.dll"

      #include <msclr\auto_gcroot.h>

      #include "Wrapper.h"

      using namespace System::Runtime::InteropServices; // Marshal
      using namespace ObjectNetwork;

      class StockWrapperPrivate
      {
      public: msclr::auto_gcroot<Stock^> stock;
      };

      StockWrapper::StockWrapper(const char* name)
      {
      _private = new StockWrapperPrivate();
      _private->stock = gcnew Stock(gcnew System::String(name));
      }

      const char* StockWrapper::GetName()
      {
      return (const char*)Marshal::StringToHGlobalAnsi(_private->stock->Name).ToPointer();
      }

      double StockWrapper::GetPrice()
      {
      return _private->stock->Price;
      }

      void StockWrapper::SetPrice(double price)
      {
      _private->stock->Price = price;
      }

      StockWrapper::~StockWrapper()
      {
      delete _private;
      }

      class BasketWrapperPrivate
      {
      public: msclr::auto_gcroot<Basket^> basket;
      };

      BasketWrapper::BasketWrapper()
      {
      _private = new BasketWrapperPrivate();
      _private->basket = gcnew Basket();
      }

      void BasketWrapper::AddStock(StockWrapper& s)
      {
      Stock^ stock = gcnew Stock(gcnew System::String(s.GetName()));
      stock->Price = s.GetPrice();

      _private->basket->AddStock(stock);
      }

      StockWrapper** BasketWrapper::GetAllStocks()
      {
      cli::array^ stocks = _private->basket->AllStocks;

      StockWrapper** unmanaged = new StockWrapper*[stocks->Length];

      for (int i = 0; i < stocks->Length; ++i)
      {
      StockWrapper* wrapper = new StockWrapper((const char*)Marshal::StringToHGlobalAnsi(stocks[i]->Name).ToPointer());
      wrapper->SetPrice(stocks[i]->Price);

      unmanaged[i] = wrapper;
      }

      return unmanaged;
      }

      BasketWrapper::~BasketWrapper()
      {
      delete _private;
      }

      And the header file:
      class StockWrapperPrivate;
      class BasketWrapperPrivate;

      class __declspec(dllexport) StockWrapper
      {
      private: StockWrapperPrivate* _private;

      public: StockWrapper(const char*);
      public: ~StockWrapper();

      public: const char* GetName();

      public: double GetPrice();
      public: void SetPrice(double);
      };

      class __declspec(dllexport) BasketWrapper
      {
      private: BasketWrapperPrivate* _private;

      public: BasketWrapper();
      public: ~BasketWrapper();

      public: const char* GetName();

      public: void AddStock(StockWrapper&);

      public: StockWrapper** GetAllStocks();
      };

      And a native C++ program:
      #include <iostream>

      #include "Wrapper.h"

      int main()
      {
      const char* name = "GOOG";
      StockWrapper Google(name);

      std::cout << "Name: " << Google.GetName() << std::endl;

      BasketWrapper basket;
      basket.AddStock(Google);

      StockWrapper** stocks = basket.GetAllStocks();

      std::cout << "First stock name: " << stocks[0]->GetName() << std::endl;
      std::cout << "Second stock name: " << stocks[1]->GetName() << std::endl;
      std::cout << "Third stock name: " << stocks[2]->GetName() << std::endl;
      }

      Result:
      Name: GOOG
      First stock name: A
      Second stock name: B
      Third stock name: GOOG

      Hope this helps.

  34. Thanks this has been very helpful. I do have a question as far as memory management goes. In the method GetValues who or what is responsible for free’ing the memory allocated by unmanagedValues? If the CLR’s are different from the dll and the calling exe does that pose an issue? In my case the exe is MFC C++ 6 while the dll is in C#/.NET 4/CLR 10.

    Many Thanks!

    • Thanks for the feedback Tim.
      AFAIK in a mixed context there is two heaps:
      – the unmanaged one used by new in native C++,
      – the managed one used by gcnew in managed C++ and by new in C#.
      But there is a single process and (most often) a single CLR, so there is no issue of this kind.
      The only issue you can have is differing bitnesses: e.g. 64 for the native process and 32 for the managed DLL.
      If you need to manage memory you should expose an additional FreeValues method that would take care of freeing the memory it allocated on the native heap.

  35. Pingback: Call C# Functionality from a C++ Native app without CLR [closed] - DexPage

  36. Hi Pragmateek,

    many thanks for sharing this post with us.
    It helps me lot on a project where I have to include a communication library written in C# by my colleagues to my native C++ application.

    Regards
    Jörg

  37. I am totally new in this kind of topic :
    This is my header file ::
    #pragma once

    using namespace System;
    class YahooAPIWrapperPrivate;

    class __declspec(dllexport) YahooAPIWrapper
    {
    private: YahooAPIWrapperPrivate* _private;

    public: YahooAPIWrapper();

    public: ~YahooAPIWrapper();

    public: double GetBid(const char* symbol);

    public: double GetAsk(const char* symbol);
    };

    And this is YahooAPIWrapper.cpp::
    #include “Stdafx.h”
    #using “E:\\YahooAPI.dll”

    #include “YahooAPIWrapper.h”
    #include

    using namespace System::Runtime::InteropServices; // Marshal

    class YahooAPIWrapperPrivate
    {
    //public: msclr::auto_gcroot yahooAPI;
    //public: msclr::auto_gcroot YahooAPI;
    public: msclr::auto_gcroot yahooAPI;
    };

    //class __declspec(dllexport) YahooAPIWrapper
    //{
    //

    YahooAPIWrapper::YahooAPIWrapper()
    {
    _private = new YahooAPIWrapperPrivate();
    _private->yahooAPI = gcnew YahooAPI();
    }

    double YahooAPIWrapper::GetBid(const char* symbol)
    {
    return _private->yahooAPI->GetBid(gcnew System::String(symbol));
    }

    double YahooAPIWrapper::GetAsk(const char* symbol)
    {
    return _private->yahooAPI->GetAsk(gcnew System::String(symbol));
    }

    YahooAPIWrapper:: ~YahooAPIWrapper()
    {
    delete _private;
    }

    Now I got errors :::
    1. GetAsk is not a member of ‘msclr::auto_gcroot’
    2. GetBid is not a member of ‘msclr::auto_gcroot’
    3. syntax error: ‘>’
    4. syntax error: identifier ‘YahooAPI’
    5. ‘YahooAPIWrapperPrivate’ : no appropriate default constructor available
    6. binary ‘->’ : no operator found which takes a left-hand operand of type ‘msclr::auto_gcroot’ (or there is no acceptable conversion)
    7. ‘YahooAPI’ : illegal use of namespace identifier in expression
    8. ‘msclr::auto_gcroot’ : too few template arguments
    9. IntelliSense: namespace “YahooAPI” is not a type name

    Can you tell me what I am doing wrong here? And can you suggest me some articles which help to improve my concepts like this?
    Thanks, this is very useful cause After two days I found this. Really this is good article.

    • auto_gcroot should be typed with the .Net/C# type:
      public: msclr::auto_gcroot<YahooAPI^> yahooAPI.
      Fix that one and it should work far better. 🙂

  38. Hi. Firstly let me thank you for the very informative article, but also for taking the time to respond to each and every comment – much appreciated!

    I’m attempting to re-use your examples to wrap up my own C# DLL using VS2015, but even though I currently only have the bare framework of the C++ wrapper I am having compile problems due to the C++ reporting that my C# class is undefined.
    – It seems I can’t add a C# project reference to the C++ project
    – I have tried the full path in the #using statement for the DLL
    – I have added the C# dll output folder to as an additional include directory and and additional #using directory.

    It’s as though the class is not exposed in the C# based DLL, yet the only major difference to your own example I have noted is that my C# class is defined within a namespace (reading previous comments you have indicated this should not matter).

    I am about to re-use your example code as a VS2015 solution (rather than individual files to be compiled at the command line), but I have already noted a runtime problem with your test application when build on my machine…..

    Unhandled Exception: System.FormatException: Input string was not in a correct f
    ormat.
    at System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
    at System.Double.Parse(String s, IFormatProvider provider)
    at YahooAPI.ParseDouble(String value)
    at YahooAPI.GetBid(String symbol)
    at YahooAPIWrapper.GetBid(YahooAPIWrapper* , SByte* symbol)

    My build output is the same as yours (though compiler version 19 identified rather than 10), with the exception one additional warning.

    E:\Devtools\Microsoft VS2015\VC\INCLUDE\exception(358): warning C4577: ‘noexcept’ used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc

    Even applying the suggest /EHsc switch it still gives the same runtime exception.

    Do you know why you example is not working when built using the VS2015 command line compiler?

    Do you have any insights into why my C# class may not be visible to the C++ code?

    Paul Parkins

    • It seems I can add a reference to the C# project after all. VS was not allowing me as my C# was targetted for .Net 4.5.2 and the C++ defaulted to 3.5.

      Using the information in the link below I determine you can only change your C++/CLR libraries targetted version by manually editing the .vcxproj file. http://stackoverflow.com/questions/2921702/change-c-cli-project-to-another-framework-than-4-0-with-vs2010

      So now I have managed to add a reference – though my C# is still reported as undefined 🙁 Still at least I got past one blocker, lol

      • I had to add an entry to my C++ such as this in order to be able to use my C# class

        using namespace mynamespace;

        • Hi Paul,
          so you’ve managed to compile using VS 2015?
          As for your runtime error I will try a guess: maybe the data returned by Yahoo are wrong: depending on the time bid/ask can be empty I imagine.
          Debugging should tell you more…

          • Indeed the Yahoo API seems to have changed the codes used to identify the fields.
            I’ve updated the article and code archive accordingly.

    • I got the same FormatException. It was caused by the values returned by the Yahoo API (mainly ‘N/A’). Maybe the API has changed.

      I did the following changes to the YahooAPI-class based on information from this page: http://www.jarloo.com/yahoo_finance/

      YahooAPI.cs
      Changed UrlTemplate to this:
      private const string UrlTemplate = “http://download.finance.yahoo.com/d/quotes.csv?s={0}&f={1}”;

      Changed the field identifiers used by GetBid() and GetAsk():
      public double GetBid(string symbol)
      {
      return ParseDouble(GetDataFromYahoo(symbol, “b”)[0]);
      }

      public double GetAsk(string symbol)
      {
      return ParseDouble(GetDataFromYahoo(symbol, “a”)[0]);
      }

      In the file Test.cpp I changed the call to yahoo.GetValues() to this:
      const char** bidAskCapi = yahoo.GetValues(stock, “abj1”);

      In production code you would of course use double.TryParse instead of double.Parse for better error handling.

      The C4530 is not related to the FormatException, I just ignored it, no problem.

      I use VS2012 Express and .NET 4.0 compilers.

  39. I think, you are aware about “send to” -> “mail recipient”. If not look at this image :: http://www.guidingtech.com/assets/postimages/2012/10/send-to-mail.png
    I am calling dll file when user clicks on “send to” -> “mail recipient”. I sat dll path in registry and file is called perfectly. But the issue is, I want to make dll using c# code, and in c# I cannot specify entry point like c++ code – BOOL APIENTRY DllMain. So how do I call function of dll which created in C#.

    Is there any way in c# to specify an entry point?

    So I found that I can not specify an entry point using C# code, so I came with another solution. And the solution is, using c++ dll entry point, I will call function of c# dll. Do you have some suggestion about this?

    • Sorry to respond so late but I have not received any notification for your comment. :/
      You can indeed use the technique shown in this article: develop your extension in C#, wrap it in a C++/CLI DLL.
      I think you don’t need a native C++ DLL as the C++/CLI one should be able to expose a DllMain entry-point.

  40. G;Day Paul,

    Just came across your article and it was a great help in interfacing some crusty old c application to some useful C# functionality contained in various c# dll’s etc.. Thank you for publishing it. =)

    However, in your example I am concerned with the two methods;

    1. const char* GetCapitalization(const char* symbol)
    2. const char** GetValues(const char* symbol, const char* fields)

    They both use Marshal::StringToHGlobalAnsi(…) to allocate unmanaged memory on the heap with the contents of the managed string. If you read the documentation on it, it is pretty clear that this heaped allocation should be explicitly freed. when your done with it i.e.

    “StringToHGlobalAnsi is useful for custom marshaling or when mixing managed and unmanaged code. Because this method allocates the unmanaged memory required for a string, always free the memory by calling FreeHGlobal.”

    Due to the fact that my application is passing around quite large string buffers from managed to unmanaged, these could be a source of potential large memory leaks

    Do you have any ideas on how to get around this? I attempted to save this heaped memory in a private member of of the wrapper class (not private) and then call FreeHGlobal when the dtor is called but that crashed the app.

    In my case, the data is not changed so I toyed with the idea of using a pin_ptr to a pass the internal ptr back but this is no good as the pin_ptr goes out of scope when you leave the managed methods scope.

    Anyway, as you can tell I am a little out of my depth on this, any suggestions on this would be much appreciated.

    Cheers.

  41. Hi,

    glad this article has been useful to you. 🙂

    You’re right, memory allocated by StringToHGlobalAnsi should be freed.
    I’ve overlooked it here as this is not an issue with such a small PoC.

    As for the correct way to handle it I would have proceeded exactly like you did.
    AFAIK the memory is allocated on the native heap so you should not be concerned with GC mechanics and pinned memory.

    I’d be curious to see some code that crashes when FreeHGlobal is called.

    Regards.

    • G;Day Pragmateek,

      Just a quick followup, I was able to finally get it to work by using my initial idea of persisting the IntPtr returned by StringToHGlobalASCII in a private member of my wrapper and freeing it when it is deconstructed. Not sure what was the problem the first time I tired it out.

      Anyway. thanks again.

  42. Helllo pragmateek,
    thank you a lot for your article since it was very helpful for me.
    I have a question regarding passing a value by reference.

    For example if i have a c# function like:
    public bool DoSomething(int input, out double output);

    Could you explain to me how my wrapper function should look like so that i can pass a reference or whatever it needs to be so that the function can set the variable ‘output’?

    Best regards
    Daniel

      • Hi Daniel,

        thanks for your feedback.

        I have a sample for such a use-case above with the LoadCodes method.
        I’ve used a pointer but as in C++ references are pointers in disguise you probably can use a reference too.

        Let me know if it works as expected.

        • Thank you for you quick response.
          Yeah both ways are possible. I just made the mistake that, when i worked with pointers i wanted to pass the pointer to the c# function…

  43. Hey there, thanks so much for the article. First one that’s ever gotten me close to using my VB.net DLL in native C++. However…. I’m getting an error. My vb.net DLL is just an adding function ( so no need to pay attention to it… but VB.net should work as well since C# and VB work on .NET)
    Here’s my Header (trying.h)
    class AddWrapperPrivate;

    class __declspec(dllexport) AddingWrapper
    {
    private: AddWrapperPrivate* _private;

    public: AddingWrapper();
    public: ~AddingWrapper();

    public: int Adding(double* x, double* y);
    };

    here’s my CLR .cpp
    using namespace System::Runtime::InteropServices;

    class AddWrapperPrivate
    {
    public: msclr::auto_gcroot add;
    };

    class __declspec(dllexport) AddingWrapper {

    private: AddWrapperPrivate* _private;
    public: AddingWrapper()
    {
    _private = new AddWrapperPrivate();
    _private->add = gcnew Add();
    };
    public: int Adding(double* x, double* y) {
    return _private->add->Adding(*x, *y);
    };
    public: ~AddingWrapper()
    {
    delete _private;
    };
    };

    And here’s my console app:
    #include “stdafx.h”
    #include
    #include
    #include “C:\Users\mleclai3\Documents\Visual Studio 2015\Projects\Trying\Trying\Trying.h”
    int main()
    {
    double* x =0 ;
    double* i =0;
    AddingWrapper add;
    std::cout <> *x;
    std::cout <> *i;

    int result =add.Adding(x,i);
    std::cout << "result is:" <> *x;
    return 0;
    }

    3 things happen:

    If I don’t compile my console app in Release x86 I get this error : unresolved external symbol “public: __thiscall AddingWrapper::AddingWrapper(void)” (??0AddingWrapper@@QAE@XZ) FOR ALL Trying.cpp functions

    If I compile it in Release x86 Then I’ll get an error that says my *x variable points to a null object (???)

    Finally, If i write my Trying.h the way you did your header I get an error c2011 ‘AddingWrapper’ : ‘class’ type redefinition

    You think you could give me some help figuring it out?

    • After compiling it with the library… It just throws me another error ( god help me please) :

      An unhandled exception of type ‘System.AccessViolationException’ occurred in AddingWrapper.dll

      Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

      More precisely:

      Unhandled Exception: System.AccessViolationException : attempted to read or write protected memory. This is often an indication that other memory is corrupt. at gcroot (Add ^).. P$AAVAdd@@(gcroot(Add^)) at AddingWrapper.Adding(AddingWrapper, double* x, double* y)

      Did your code ever do that???

      • Hi Marc,

        let’s tackle your issues one by one:
        1) The build chain bitness must be consistent: if any of the dependencies is in x86 (32-bit) your calling code must be in x86 too.
        By default you’re probably using the x86 build chain with CL x86.
        The linker will not consider dependencies with a different bitness as itself, hence won’t take symbols contained in them into account, hence your error.
        2) In the main x and i are pointers (variables containing memory addresses) so you must initialize them with valid addresses (owned by the process).
        But you don’t need them and you should do something like that instead:

        int main()
        {
            double x = 0;
            double i = 0;
            AddingWrapper add;
            std::cout << x;
            std::cout << i;
        
            int result = add.Adding(&x, &i);
            std::cout << "result is:" < < x;
            return 0;
        }

        3) Indeed in the .cpp you should not define class members as I did (not a best practice I confess).
        Instead you should have no class AddingWrapper { ... } declaration but only members definitions:

        AddingWrapper::AddingWrapper()
        {
            _private = new AddWrapperPrivate();
            _private->add = gcnew Add();
        };
        int AddingWrapper::Adding(double* x, double* y)
        {
            return _private->add->Adding(*x, *y);
        };
        ...

        4) The runtime error is the direct consequence of point 2):
        when you write double* x = 0 you say "x is pointing to the first memory address" which is an invalid address for your process;
        so when you do *x you're trying to get the value stored at this invalid address and the OS logically answers you can't do that with the AccessViolationException (segmentation fault).

        Hope this helps.

        Tell me if you manage to get it to work or if you have any other issue.

    • Hi Steve,
      what issue have you with your VS 2010 solution?
      You should have 3 projects: 1 for the .Net API, 1 for the C++/CLI wrapper, and 1 for the native application.

  44. I created a C# class library for the YahooAPI. Then I added another project containing a C++ header and source file for YahooWrapper supporting CLR. The last project consists of the test.cpp. I have a problem in the following class in the YahooWrapper:

    class YahooAPIWrapperPrivate
    {
    public: msclr::auto_gcrootyahooAPI;
    }
    I am getting the error “class msclr:: auto_gcroot<>, wrap a resource to enforce strict ownership d ensure proper clean up. “YahooAPI” is not a type name.”

    I would appreciate any help.
    Thanks

  45. I have this header file

    // ClassLibrary4.h

    using namespace System;
    using namespace Microsoft::Kinect;
    using namespace std;
    using namespace System::Runtime::InteropServices;
    //using namespace Distance_Test;
    //#using

    class clrPrivate;

    class __declspec(dllexport) clr
    {

    private: clrPrivate* _private;
    public: clr();
    public: ~clr();
    public: String^ calculate( Double Robot_Points_Values[],array human_point_cloud , unsigned char bodyindexdata[]);

    // TODO: Add your methods for this class here.
    };

    and for .cpp this:

    using namespace Distance_Test;
    using namespace std;
    using namespace System::Runtime::InteropServices; // Maratos
    using namespace Microsoft::Kinect;
    using namespace System;

    class clrPrivate
    {
    public: msclr::auto_gcrootDistance_Calc_Library_Test21;
    };

    clr::clr()
    {

    _private = new clrPrivate();
    _private->Distance_Calc_Library_Test21 = gcnew MINIMUM_DISTANCE();
    }

    String^ clr::calculate(Double Robot_Points_Values[], array human_point_cloud, unsigned char bodyindexdata[])
    {
    //String^ output = _private->Distance_Calc_Library_Test21->calculate(gcnew Double(Robot_Points_Values), (gcnew CameraSpacePoint human_point_cloud), gcnew(unsigned char bodyindexdata));
    //return _private->Distance_Calc_Library_Test21->calculate->value_return(Robot_Points_Values,human_point_cloud,bodyindexdata);

    String^ output = _private->Distance_Calc_Library_Test21->calculate.value_return( Robot_Points_Values,human_point_cloud,bodyindexdata);
    }
    //return output;
    //return _private->Distance_Calc_Library_Test21->calculate->(gcnew String^( robot_position, human_point_cloud, bodyindexdata));

    clr::~clr()
    {
    delete _private;
    }

    but i have these 2 errors :
    1)Error C3395 ‘clr::calculate’: __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention Line 19 of my ClassLibrary4.h
    2)Error C2228 left of ‘.value_return’ must have class/struct/union ClassLibrary4.cpp Line 32 of my ClassLibrary4.cpp

    Could you please give me some help?

  46. Thank you for updating this article with new memory control. Lots of examples out there with managed calling native, not so many with native calling managed. I originally used the “ManWrap” stuff from ages ago and everything started breaking on win 10 and server 2012. I got that to work then XP broke. I will be updating my “ManWrap” based stuff to this. A much more straight forward approach. Hopefully that will fix the mystery problem I was having when code gated from native to CLI. I will let you know how it works out.

  47. Hi, thank you for your article, your sample is working well. Instead I have a question if you can help me please. How can I notify from my c# dll the c++/cli module that an event is triggered?

    Thank you in advance.

    • Hi,

      here is a sample I did for another similar request:
      – the C# API which raises events:

      using System.Threading;
      
      public delegate void OnMessageDelegate(string message);
      
      public class StockAPI
      {
      	public event OnMessageDelegate OnMessage = delegate { };
      	
      	public void Connect()
      	{
      		OnMessage("Connecting...");
      		
      		Thread.Sleep(1000);
      		
      		OnMessage("Connected.");
      	}
      }

      – the C++/CLI wrapper:

      using namespace System;
      using namespace System::Collections::Generic;
      #using "StockAPI.dll"
      
      #include <vector>
      #include <msclr\auto_gcroot.h>
      
      using namespace System::Runtime::InteropServices; // Marshal
      
      
      // Need a managed type to handle events raised by the C# class.
      ref class StockAPIEventsHandler
      {
          private: List<IntPtr>^ onMessageCallbacks;
      
          public: StockAPIEventsHandler(StockAPI^ stockAPI)
          {
              onMessageCallbacks = gcnew List<IntPtr>();
              stockAPI->OnMessage += gcnew OnMessageDelegate(this, &StockAPIEventsHandler::OnMessage);
          }
      
          private: void OnMessage(System::String^ message)
          {
              IntPtr ptr = Marshal::StringToHGlobalAnsi(message);
      
              const char* msg = (const char*)ptr.ToPointer();
      
              for (int i = 0; i < onMessageCallbacks->Count; i++)
              {
                  void (*ptr)(const char*) = (void (*)(const char*))onMessageCallbacks[i].ToPointer();
      
                  ptr(msg);
              }
      
              // Avoid memory leak.
              Marshal::FreeHGlobal(ptr);
          }
      
          public: void RegisterOnMessage(void (*callback)(const char*))
          {
              IntPtr ptr(callback);
      
              onMessageCallbacks->Add(ptr);
          }
      };
      
      class StockAPIWrapperPrivate
      {
          public: msclr::auto_gcroot<StockAPI^> stockAPI;
          public: msclr::auto_gcroot<StockAPIEventsHandler^> stockAPIEventsHandler;
      };
      
      class __declspec(dllexport) StockAPIWrapper
      {
          private: StockAPIWrapperPrivate* _private; 
      
          public: StockAPIWrapper()
          {
              StockAPI^ stockAPI = gcnew StockAPI();
              _private = new StockAPIWrapperPrivate();
              _private->stockAPI = stockAPI;
              _private->stockAPIEventsHandler = gcnew StockAPIEventsHandler(stockAPI);
          }
       
          public: void Connect()
          {
              return _private->stockAPI->Connect();
          }
       
          public: void OnMessage(void (*callback)(const char*))
          {
              _private->stockAPIEventsHandler->RegisterOnMessage(callback);
          }
       
          public: ~StockAPIWrapper()
          {
              delete _private;
          }
      };

      – the C++/CLI wrapper’s header file:

      class StockAPIWrapperPrivate;
       
      class __declspec(dllexport) StockAPIWrapper
      {
          private: StockAPIWrapperPrivate* _private;
       
          public: StockAPIWrapper();
           
          public: ~StockAPIWrapper();
           
          public: void Connect();
       
          public: void OnMessage(void (*callback)(const char*));
      };

      – the native C++ program:

      #include <iostream>
       
      #include "StockAPIWrapper.h"
      
      void onMessage(const char* msg)
      {
          std::cout << "Message received: '" << msg << "'" << std::endl;
      }
      
      int main()
      {
          StockAPIWrapper stockAPI;
          
          stockAPI.OnMessage(onMessage);
      
          stockAPI.Connect();
      }

      Compilation steps:
      – C# API: csc /target:library StockAPI.cs
      – C++/CLI wrapper: cl /clr /LD StockAPIWrapper.cpp
      – native C++ program : cl main.cpp StockAPIWrapper.lib

  48. Hi,
    Thank you for the article. Just working on the similar problem.
    I am wonder about necessity __declspec(dllexport) .as far as code used as static library.
    Also to proper apply pimpl idoom it looks better to use smart-pointers.
    I have changed a while the code by replacing ptr to unique_ptr and make
    YahooAPIWrapper class a proxy. The class functions just repeat in YahooAPIWrapperPrivate and all marshaling done inside.
    So at the end it works exactly the same. Here the changes if you interesting in:

    //YahooAPIWrapper.h
    #include <memory>
    
    class YahooAPIWrapperPrivate;
    
    //class __declspec(dllexport) YahooAPIWrapper
    class YahooAPIWrapper
    {
        //private: YahooAPIWrapperPrivate* _private;
        private: 
            std::unique_ptr _private;
    
        public: 
            YahooAPIWrapper();
            ~YahooAPIWrapper();
        
            double GetBid(const char* symbol);
            double GetAsk(const char* symbol);
            const char* GetCapitalization(const char* symbol);
            const char** GetValues(const char* symbol, const char* fields);
    };
    
    //YahooAPIWrapper.cpp
    
    #using "YahooAPI.dll"
    
    #include <memory>
    
    #include "YahooAPIWrapper.h"
    
    using namespace System::Runtime::InteropServices; // Marshal
    
    class YahooAPIWrapperPrivate
    {
        public:
    
            double GetBid(const char* symbol);
            double GetAsk(const char* symbol);
            const char* GetCapitalization(const char* symbol);
            const char** GetValues(const char* symbol, const char* fields);
    
        private: 
            msclr::auto_gcroot yahooAPI = gcnew YahooAPI();
    };
    
    
    double YahooAPIWrapperPrivate::GetBid(const char* symbol)
    {
        return yahooAPI->GetBid(gcnew System::String(symbol));
    }
    
    double YahooAPIWrapperPrivate::GetAsk(const char* symbol)
    {
        return yahooAPI->GetAsk(gcnew System::String(symbol));
    }
    
    const char* YahooAPIWrapperPrivate::GetCapitalization(const char* symbol)
    {
        System::String^ managedCapi = yahooAPI->GetCapitalization(gcnew System::String(symbol));
    
        return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();
    }
    
    const char** YahooAPIWrapperPrivate::GetValues(const char* symbol, const char* fields)
    {
        cli::array^ managedValues = yahooAPI->GetValues(gcnew System::String(symbol), gcnew System::String(fields));
    
        const char** unmanagedValues = new const char*[managedValues->Length];
    
        for (int i = 0; i Length; ++i)
        {
            unmanagedValues[i] = (const char*)Marshal::StringToHGlobalAnsi(managedValues[i]).ToPointer();
        }
    
        return unmanagedValues;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    YahooAPIWrapper::YahooAPIWrapper()
    {
        _private = std::make_unique();
    }
    
    double YahooAPIWrapper::GetBid(const char* symbol)
    {
        return _private->GetBid(symbol);
    }
    
    double YahooAPIWrapper::GetAsk(const char* symbol)
    {
        return _private->GetAsk(symbol);
    }
    
    const char* YahooAPIWrapper::GetCapitalization(const char* symbol)
    {
        return _private->GetCapitalization(symbol);
    }
    
    const char** YahooAPIWrapper::GetValues(const char* symbol, const char* fields)
    {
        return  _private->GetValues(symbol, fields);
    }
    
    YahooAPIWrapper::~YahooAPIWrapper()
    {
        // delete _private;
    }

    What do you think?

    • Hi Alex,
      thanks for your feedback and for sharing your enhancements.
      I’ve added some code markup so all code should be visible now.
      Do not hesitate to fix it.
      As for the __declspec(dllexport) you may be right indeed, but I’m far from being a C++ expert. 🙂

  49. sry it’s eat some symbols in the code. IN YahooAPIWrapper.h
    need include memory.h and use unique_ptr instead of ptr to avoid delete in destructor.

  50. Hi,

    Just wanted to say thanks for this article!
    Information on this subject is scarce on the net, and I think your article is the best I’ve found.

    Cheers.

  51. Hi Sir,

    thanks for your article, It really helped me to understand this concept. I am here trying to use the existing C# API in native C++. While doing so, as you mentioned i am trying to use SWIG to generate the C++\CLI wrapper using my C# API assembly. But i couldnt see the help for the same, instead i am seeing the reverse to use C++ in C#. Can you please let know where should i find help to generate C++\CLI wrapper using my C# Code?

    • Hi,
      thanks for the feedback. 🙂
      As for SWIG indeed it won’t be a good fit for this use-case.
      I fear you’ll have to write the wrappers yourself as described in this article or use some other intermediate layer that might ease the interfacing, like COM.
      Indeed COM as some tools to automatically generate metadata components (type libraries TLBs) that would act like a pivot between the two worlds (.Net and C++).
      The idea would be to generate the TLB from the C# code with TLBEXP and to import it on the native C++ side.
      Of course COM comes with its own set of issues and craftsmanship so if you have never worked with it it’s probably not worth the trouble to learn it.
      So if you have a few classes sticking with the manual C++/CLI wrapper creation is the easier and safer path.

  52. I have a unusual issue here… I have a “c# .dll” that communicates with a SOAP Web Service, and I’m working in an old project developed in Gupta CTD 3.0… In that enviroment I can call .dll’s, but not written in C#, I’ve tried with one made in c++ and it worked… So, my question is if I can use this shown method to make a c++ .dll that communicates through a c++/cli wrapper to my c# .dll… I don’t know if I was clear enough. Thank you for the post!

    • Yes your use-case is exactly covered by this article, so you can directly use the technique presented here.
      Hopefully it won’t be too difficult, especially if your API is quite simple.

  53. Hello, thanks for the nice tutorial.
    I am getting an error in my native c++ code when I define the object of YahooAPIWrapper class. I am using vs2015.

    First I created C# class library in order to generate the C# dll. I copied the source code exactly as mentioned in the tutorial. Then for the C++/CLI part, I created a new C++ CLR Class library and copied the source code into YahooAPIWrapper.cpp and .h. This generates a dll and lib file. Now, I create a C++ project and include the header file in main.cpp. For including the library, I mentioned the location in “Additional Library directories” in Linker->General and also mention the lib file in Linker->Input.
    Now when I run this code, I get the following error:

    Unhandled exception at 0x739E08C2 (KernelBase.dll) in CallYahooWrapper.exe: 0xE0434352 (parameters: 0x80070002, 0x00000000, 0x00000000, 0x00000000, 0x72260000).

    This occurs at the line – YahooAPIWrapper yahoo;

    Could you please help me with the error.
    Thanks

    • I also tried your VS project. I get the same error. Your project is able to declare the object yahoo, but the error occurs when yahoo.GetBid(…) is called.

      • Hello,
        thanks for the feedback.
        Maybe this is due to the Yahoo API being down.
        Please check with a basic code not requesting data from it.

        • Thanks for your reply.

          I tried the following and it worked successfully.

          I removed all the methods given in your code and made a simple code which shows a message box and it worked.

          • Glad all is running fine now.
            I don’t know what they’ve changed and why but indeed it has broken my samples. 🙁

  54. Hello Pragmateek,
    I have used this wrapper for various projects. I am able to pass single variables such as int or string using the wrapper between c# and c++. I am currently stuck on passing byte array.

    I have a c# dll for which i have made a c++cli wrapper. With this I can call the c# functions in native c++. The c# code has an image as a byte array and bitmap. I want to pass this image to native c++ code for further usage. I have checked various links on SO and it seems that there is a solution using Lockbits but I do not understand it. Is it possible for you to make a tutorial for the same or give some good sources.
    Thanks

    • Hello Ankit,
      depending on your use-case you could try to let the Bitmap operations on the C# side, and only command them from C++ through more simple method calls.
      I’ve never used the Bitmap API but the MSDN sample seems similar to your use-case: Bitmap.LockBits
      Except that in your case you would pass a pointer to the copied array back to C++ instead of manipulating it on the C# side.

  55. I would just like to say, as a fellow developer/blogger and C++ wrangler, the energy and commitment you’ve put into helping each and every poster here is, without doubt, inspirational and admirable. You deserve a medal!

  56. Hello. There is a function:
    public void Evaluate(ref float Res, ref List inputData)
    {
    List input0Combined = new List();
    input0Combined.AddRange(inputData);

    List result = manager.RunModel(modelName, int.MaxValue, evaluateInputNames,
    new List { new Tensor(input0Combined, new List { 1, 1, 48 }) }, evaluateOutputNames);

    List tmp = new List();
    result[0].CopyTo(tmp);
    Res = 0;
    Res = tmp[0];
    }
    And there is a dll by your example:
    #using “CntkAPI.dll”
    #include “stdafx.h”
    #include
    #include “DLLCriD.h”

    using namespace System::Runtime::InteropServices; // Marshal

    class LoadAPIModel
    {
    public: msclr::auto_gcrootcntkNET;
    };

    ClassNet::ClassNet()
    {
    pmodel = new LoadAPIModel();
    (*pmodel).cntkNET = gcnew CntkAPI::CntkNET();
    }

    void ClassNet::Evaluate(float& Res, std::list& inputData)
    {
    pmodel->cntkNET->Evaluate(Res, … ); // Here is the problem
    }
    ClassNet::~ClassNet()
    {
    delete pmodel;
    pmodel = nullptr;
    }

    How to transfer a list to a function?
    I would appreciate any hint.

  57. Loaded projects into VS 2015 (it upgraded the Wrapper), built OK but run/debug failed with
    Unhandled exception at 0x75e21812 in Test.exe: 0xE0434352: 0xe0434352.
    Trying to find a solution like this – calling C# code from native C++ – and nothing works

  58. Thanks pragmateek. This is nice and helpful tutorial.
    I have an application which is developed in C++ we can say it A . I have made a wrapper B.dll which is calling C# C.dll. C.dll has the functionality which is running a thread. By referring above example I am able to call methods present in C.dll and successfully passed parameters but thread isnt going up.

    C.dll
    public void CallFromWrapper(Structure_variable V1)
    {
    // I am able to access the parameters present in V1 strucure coming from the Wrapper B.dll application.
    Thread newThread = new Thread(() => dummyCalltoCSharpAPI(V1));
    newThread.SetApartmentState(ApartmentState.STA);
    newThread.Start();
    }

    public void dummyCalltoCSharpAPI(Structure_variable V1)
    {
    Application.Run(new C(V1)); //Here C is the constructor
    }

    But it is not starting the “C” constructor after following all the steps. Inside “C” constructor there is UI present.

    • Hi Abhi,
      is it a Winforms or WPF application?
      I wonder if the issue might be that the main thread is terminating so the process is killed.
      Try to run the message-loop on the main thread, i.e. do not call Application.Run in a dedicated thread but directly in CallFromWrapper.

      • Hey Pragmateek team.Thank you for your quick response.
        It is Winform application.
        I have called directly “Application.Run” in “CallFromWrapper” It is working fine now. 🙂

    • I have a query again, in wrapper B.dll which is calling C# C.dll. Where C.dll returning a structure array. I have did following thing and it is not calling the method from C.dll.

      B.dll

      class BCLIAPIWrapperPrivate
      {
      public: msclr::auto_gcroot API;
      };

      BCLIAPIWrapper::BCLIAPIWrapper()
      {
      _private = new BCLIAPIWrapperPrivate();
      _private->API = gcnew C_NAMESPACE::C_ClassName();
      }

      native_structure* BCLIAPIWrapper :: CallFromWrapper(Structure_variable V1)
      {
      C_NAMESPACE::Managed_Structure_variable managedObj1;
      // copied all structure data in managedObj1 here from V1
      cli::array^
      managedStructObj2 = _private->API->CallFromWrapper(managedObj1);

      //Copied all data from managedStructObj2 to NativeStructObj manually

      return NativeStructObj;
      }

      A.dll
      BCLIAPIWrapper BAPIWrapperObj;
      A_NATIVE_STRUCTURE *NativeRecData;
      // Code breaking here
      NativeRecData = BAPIWrapperObj.CallFromWrapper(Structure_variable V1);

      Thanks in advance. 🙂

  59. Hi,

    I’m updating a C# server from .NET 4.0 to 4.5 or higher. Without changing any code, I get a “System.AccessViolationException: ‘Attempted to read or write protected memory. This is often an indication that other memory is corrupt.’

    I’ve searched everywhere, in different forums, blogs, but nobody is able to solve my problem. Please read the following in stackexchange: https://stackoverflow.com/questions/56085130/acess-violation-protected-memory-when-editing-a-passed-intptr-from-c-sharp-to-na

    Upon finding this, I think you may be able to solve my problem because it has to do with DLLImport and passing IntPtr. Some protocol has changed to 4.5 that I need to update for this memory corruption error to go away.

    Please help.

  60. Hi – Thanks for a great tutorial! I got excited about your solution as it could be a “solution” to the proof of concept search I’ve been on to write some libraries for a 3rd party app that requires a Win32 DLL. Ideally I like to use your scheme to write the bulk of the code in a C# library and use the native library as a “pass-through”.

    To that end, the native console I’m using (based on your scheme) to test the interaction between the two libraries builds and works without any errors.

    However, when I connect the APIWrapper DLL to my 3rd party app I’m getting the error “External exception EO434352”.

    The error occurs at the point where I try to instantiate the APIWrapper class in the ‘GetRevision’ function (see comments in below code).

    Any insight would be greatly appreciated!

    // APIWrapper.h
    #pragma once

    #define DLL_EXP extern “C” __declspec(dllexport) // please note this is new – an addition to your scheme
    DLL_EXP void GetRevision(char* data_in, char *data_out);
    DLL_EXP void Foo(char* data_in, char *data_out);

    class APIWrapperPrivate;
    class __declspec(dllexport) APIWrapper
    {
    private: APIWrapperPrivate* _private;

    public:
    APIWrapper();
    ~APIWrapper();

    const char* GetRevisionFunc(const char* rev);
    };

    // APIWrapper.cpp
    // – snip –

    DLL_EXP void GetRevision(char* data_in, char *data_out)
    {
    MessageBox(NULL, TEXT(“MsgBox1”), TEXT(“Test”), MB_OK); // msgbox works!

    APIWrapper wrp; // <libraryAPI->GetRevisionUtil(gcnew System::String(rev));
    return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();
    }

    • Hi Jon,
      thanks for your feedback. 🙂
      If you only need to expose native entry-points I advise you to use a simpler way with DllExport.
      The C++/CLI wrapper approach is worth the trouble if you need to expose an object-oriented API.

      • Hi, Your last sentence gave me a bit a of a pause: “The C++/CLI wrapper approach is worth the trouble if you need to expose an object-oriented API.” … because that is what I thought I WAS attempting. 🙂
        Please note that your scheme seemed very well suited to what I’ve been trying to achieve – until I ran up against the error that I describe above.
        I guess the question is – does it seem possible to resolve the error I’m seeing?

      • Hi Pragmateek, it seems I should clarify my situation a bit.

        I’ve got some equipment for which I’ve written some VB6 functions over the years. And of course with Win10 it’s becoming increasing difficult to support these VB6 apps. So my hope has been to upgrade these functions to .Net. This would be easy enough except that I never really liked the way these apps interfaced with the 3rd party app our equipment uses. Ideally these functions would connect using a DLL.
        Over the years, at various intervals, I’ve taken a run at this task – trying to understand how to write the DLL code to make the connection. Well this year I finally figured out that piece (It should be obvious that I’m not a C++ programmer). Once I solved the first part, I then started trying to understand of it were possible to simply use the Win32 DLL to send & receive string values from a C# library – where I’m a bit more comfortable.
        And then I found your project! And it seemed like your scheme could get me very close.
        Now you mentioned using ‘DllExport, but from what I can see it’s more C++ intensive, and it doesn’t meet my main requirement – which is a Win32 DLL.

        I should note that the guidance provided by our 3rd party equipment vendor is that it expects the following structure:
        #define DLL_EXP extern “C” __declspec(dllexport)
        DLL_EXP void _MY_FUNC(char* data_in, char *data_out);

        It’s seems I’m pretty close to a solution with using your scheme – if I can just figure out how to instantiate the wrapper class without throwing the error.
        Any suggestions you could provide would be greatly appreciated.

        • Hi Jon,
          what I mean is that the API between the equipment and your code is not object-oriented, the equipment won’t instantiate some classes of yours, but will call some entry-points (~static methods) through a C interface.
          So you could follow this “tutorial” from master Hans Passant: C# Unmanaged Exports 🙂
          This is the safest and fastest path.
          Using tools like “.Net DllExport” I’ve mentioned or “Unmanaged Exports” should be easier but I’ve tried to make a PoC and unfortunately both are a complete PITA. 🙁

    • Oops! Somehow the above code lost a few lines once it was posted. Here is the pertinent “wrapper” code again:

      // APIWrapper.cpp
      // – snip –

      DLL_EXP void GetRevision(char* data_in, char *data_out)
      {
      MessageBox(NULL, TEXT(“MsgBox1”), TEXT(“Test”), MB_OK); // msgbox works here!

      APIWrapper wrp; // <libraryAPI->GetRevisionUtil(gcnew System::String(rev));
      return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();
      }

  61. I’m trying to make it work by copying and pasting the code with no changes to just get it up and running. I get compile errors on the c++ exe that will run everything. The errors are LINK2019 errors unresolved external symbol on the YahooApiWrapper methods. I’m not a C++ guy so any help would be appreciated

    • Hi Daniel,
      Sorry for the late answer but I was OOO.
      Are you using a CLI to compile?
      If so please share the commands you use.

  62. Hi, great to see an article like this which is still getting answers from the author!

    I’m trying to use this method on a .NET 5 C# dll as we want to use EntityFrameworkCore as a DB layer for a legacy native C++ application. However when my application comes to load the dlls I get the following;

    System.IO.FileNotFoundException
    HResult=0x80070002
    Message=Could not load file or assembly ‘MyDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. The system cannot find the file specified.
    Source=
    StackTrace:

    I tried to create a MyDll.runtimeconfig.json (an article I saw suggested that this would be required and wasn’t currently being generated for the c# dll) but it hasn’t made a difference. I placed it in the folder where my native C++ .exe and managed C++ apiwrapper are – and in the build folder.

    I checked I hadn’t strayed too far from your article (My file names & methods are different, but I followed the method) by building the same project but using .NET Framework 4.7.2, cut & paste my classes/code from the .NET 5 project and it works like a charm.

    I appreciate .NET 5 is still a work in progress – should I be using a different method to try this or is there any known workaround for this?

    • Hi Phil,
      I don’t know .NET 5, but as a first step I would trace the process with Process Monitor (aka ProcMon) in order to know in which places the runtime is looking for the assembly.

  63. Pingback: The Advantage of a CLI Wrapper

  64. Unhandled exception at 0x756AB662 (KernelBase.dll) in Test.exe: 0xE0434352 (parameters: 0x80131509, 0x00000000, 0x00000000, 0x00000000, 0x6F0C0000).

    Got this issue while running this project.

  65. How about going the other way from the charp code to the vc++ clr managed project to the native project.

    How would the vc++ clr managed code provide a call backfunction to the c# project that the c# project would call, and how would the vc++ clr project get a callback function pointer from the native c++ project to call

  66. Hi,

    Very nice work! I followed online instructions using different names, not Yahoo. But, structure is the same as your codes.

    I got working from C++ ->C++ CLR -> c#. I have one question. My c# part is socket comm, and receiving data, what is best way to pass received sock data to unmanaged C++ through C++ CLR?

    • Hi,
      Not events strictly speaking, but callbacks might be an option: the native code passes a native function to C# which calls it when it has something to notify about.

  67. Pingback: The Advantage of a CLI Wrapper

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove me you\'re human :) *