Reputation: 23
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
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
Reputation: 1
Use C++ COM and consume from C# code. Only if u are on windows platform.
Upvotes: 0
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
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