Guillaume
Guillaume

Reputation: 198

Exchange string between c++ and C# with DLL

I'm looking for exchange a string from my c++ code with my c# form.

Here is my code in my C# program:

[DllImport("libDLL.dll", CallingConvention = CallingConvention.Cdecl)]
            public static extern string valeurExpr(IntPtr pImg);

            public unsafe string objetLibValeurCarteExpr()
            {
                return valeurExpr(ClPtr);
            }

And my code in my C++ program :

Class IHM

 class IHM {
 private:
        std::string             card_number_str;
        std::string             card_expr_str;
        std::string             card_porteur_str;

My extern

extern "C" _declspec(dllexport) std::string valeurExpr(IHM* pImg) {     return pImg->lireExpr(); }

Function lireExpr()

 _declspec(dllexport) std::string lireExpr() const {
        return card_expr_str;
    }

When i execute Visual said that i try to access to a protected part of memory.

Upvotes: 0

Views: 831

Answers (1)

Adam Jachocki
Adam Jachocki

Reputation: 2124

First of all you cannot have std::string nor std::wstring in dll that you want to be accessible from other languages. So these fellows have to be changed to char * or wchar_t * <--- this is the real string - array of chars.

So, how to get string from C++ to C#?

C++

void foo(char *str, int len)
{
    //write here content of string
}

C#

[DllImport("...", CallingConvention = CallingConvention.Cdecl)
static extern void foo(StringBuilder str, int len);

and then you have to call it somehow:

void callFoo()
{
  StringBuilder sb = new StringBuilder(10); //allocate memory for string
  foo(sb, sb.Capacity);
}

Notice that in C# you have to use StringBuilder to get string from c++.

If you want to pass a string in the other way - from C# to C++ is simpler: C++

void foo(const char *str)
{
    //do something with this str
}

C#

[DllImport("...", CallingConvention = CallingConvention.Cdecl)
static extern void foo(string str);

and then just:

void callFoo(string str)
{
   foo(str);
}

You have to remember about codepage. So if you're using unicodes, you will have to give additional attribute to DllImport: CharSet=CharSet.Unicode

Now classes. There is NO simple way to pass a class defined in C++ to C#. The simples way is to do some magic. So for every member function in C++ create non member function that will be exported to dll. Something like that:

//class in C++
class Foo 
{
public:
  int Bar();
};

//now you will have to define non member function to create an instance of this class:
Foo* Foo_Create() 
{ 
    return new Foo(); 
}

//and now you will have to create non member function that will call Bar() method from a object:
int Foo_Bar(Foo* pFoo) 
{ 
    return pFoo->Bar(); 
}

//in the end you will have to create a non member function to delete your object:
void Foo_Delete(Foo* pFoo) 
{ 
    delete pFoo; 
}

And then you can use it in C#:

[DllImport("Foo.dll")]
public static extern IntPtr Foo_Create();

[DllImport("Foo.dll")]
public static extern int Foo_Bar(IntPtr value);

[DllImport("Foo.dll")]
public static extern void Foo_Delete(IntPtr value);

You can also use a C# class in C++, but it's a little more complicated and requires use of C++/CLI

Upvotes: 4

Related Questions