passenger
passenger

Reputation: 23

How to pass C++ Object to C#

Looking for help from experience people who have dealt with C++ and C#

I am now writing a C# project which requires calling an existing C++ function in the internal library, and encountering some difficulties.

C++ Code Function Header (Cannot be changed)

typedef int (*PTR_func) 
(const char*             param1,      // input
 const char*             param2,      // input
 VirtualInternalString&  po_output);  // Third param is actually the output

C++ Code Class for the internal string object (Cannot be changed)

namespace InternalLib
{

    class VirtualInternalString
    {
        public :
            virtual ~VirtualInternalString(){};
            virtual void _cdecl SetString(const char *) =0;
            virtual const char * _cdecl c_str() const =0;
    };

    class SafeInternalString :public VirtualInternalString
    {
        public :
            SafeInternalString():TheString(""){};
            virtual ~SafeInternalString(){};
            virtual void _cdecl SetString(const char *  chararray) { TheString = chararray;};
            virtual const char * _cdecl c_str() const { return TheString.c_str() ;} ;           // This is the std::string

        protected:
            std::string TheString;
    };

    class SafePtrString :public VirtualInternalString
    {
        public :
            SafePtrString():PtrString(0){};
            SafePtrString(std::string &str):PtrString(&str){};
            virtual ~SafePtrString(){}; 
            virtual void _cdecl SetString(const char *  chararray) { (* PtrString) = chararray;};
            virtual const char * _cdecl c_str() const { return PtrString->c_str() ;} ;

        protected :
            std::string * PtrString;
    };
}

Now I have to utilize this "func" in my C# code. I can call and use the C++ function properly, but problem occurs during output return (the third param). It should be problem related return type.

C# (Can be changed)

[DllImport("xxxxlib", CallingConvention = CallingConvention.Cdecl)]
private extern static int func(string param1, 
                               string param2, 
                               [MarshalAs(UnmanagedType.LPStr)] StringBuilder res); // problem here

I know I have to create an appropriate wrapper to decopose the c++ object into C# string but I don't have previous experience about it. I have tried several solutions from the internet but not working.

Does any one know how I can implement this? Would you mind showing me some simple C# skeleton code?

Upvotes: 2

Views: 2648

Answers (4)

N0dGrand87
N0dGrand87

Reputation: 817

In past experience, I did use SWIG tool for generation wrapper implementation It has support for C++ to wrapper generation to several languages, where Java the most popular one There is a great tutorial - http://www.swig.org/tutorial.html C# is also supported - http://www.swig.org/Doc3.0/CSharp.html

/* InternalLib.i */
%module InternalLib
%{
/* include header with a VirtualInternalString class*/
#include "InternalLib.h"
%}

then call swig to generate wrapper files:

swig -csharp InternalLib.i

Upvotes: 0

Swaraj Ketan
Swaraj Ketan

Reputation: 1

Use C++ COM and consume from C# code. Only if u are on windows platform.

Upvotes: 0

Mr.C64
Mr.C64

Reputation: 42924

This is a case in which I think using C++/CLI does make sense. You may want to build a tiny C++/CLI bridge between the native C++ DLL and your C# code.

The C++/CLI layer is responsible to take your custom C++ string class as output parameter from the DLL function, and convert from this custom string to a C#/.NET string object.

Your custom C++ string class seems to wrap std::string; on the other hand, C#/.NET strings use Unicode UTF-16 as their text encoding, so you may need to convert between Unicode UTF-8 (stored in std::string and in your custom string class) and UTF-16 (for C#/.NET strings).

Similarly, you also need to convert C# UTF-16 strings to UTF-8 in this C++/CLI bridging layer, and pass these UTF-8-encoded strings as your const char* input parameters to the native DLL function.

Upvotes: 1

CodeMonkey
CodeMonkey

Reputation: 4738

vasek's possible duplicate won't work if you only change the C# side. But what you can do is create wrappers in C++ that create raw char * with associated length parameter.

You create an additional C++ header and source which contains:

int func 
(const char*             param1,      // input
 const char*             param2,      // input
 char*                   po_output,   // Third param is actually the output
 int                     length);     // Length of the buffer allocated by caller  

And then you make your func call PTR_func.

Upvotes: 3

Related Questions