11

I thought the problem is inside my C++ function,but I tried this

C++ Function in C++ dll:

bool __declspec( dllexport ) OpenA(std::string file)
{
return true;
}

C# code:

[DllImport("pk2.dll")]
public static extern bool OpenA(string path);

    if (OpenA(@"E:\asdasd\"))

I get an exception that the memory is corrupt,why?

If I remove the std::string parameter,it works great,but with std::string it doesnt work.

1
  • Maybe you can solve it by making a managed c++ bridge that unpacks the string? Here is a SO question about this subject. Commented May 17, 2009 at 13:11

5 Answers 5

16

std::string and c# string are not compatible with each other. As far as I know the c# string corresponds to passing char* or wchar_t* in c++ as far as interop is concerned.
One of the reasons for this is that There can be many different implementations to std::string and c# can't assume that you're using any particular one.

Sign up to request clarification or add additional context in comments.

2 Comments

Not to mention that std::string is also a template, which opens another interesting can of worms for the interop.
The most proper way is to use char* and create std::string from it. If you want to return a std::string to C#, you must allocate a char* with CoTaskMemAlloc with size of std::string's size()+1, then memcpy std::string's data() into this buffer and return it. Easy. Note: you MUST use CoTaskMemAlloc!
7

Try something like this:

bool __declspec( dllexport ) OpenA(const TCHAR* pFile)
{ 
   std::string filename(pFile);
   ...
   return true;
}

You should also specify the appropriate character set (unicode/ansi) in your DllImport attribute.

As an aside, unrelated to your marshalling problem, one would normally pass a std:string as a const reference: const std:string& filename.

1 Comment

that std::string will fail compilation if _UNICODE is defined. might be better to do an #ifdef and use std::wstring or simply make a typedef for a tstring depending on _UNICODE.
2

std::wstring and System.string can be compatible through below conversion:

C++ :

bool func(std::wstring str, int number)
{
  BSTR tmp_str = SysAllocStringLen(str.c_str(), str.size());
  VARIANT_BOOL ret = VARIANT_FALSE;

  // call c# COM DLL
  ptr->my_com_function(tmp_str, number, &ret);

  SysFreeString(tmp_str);

  return (ret != VARIANT_FALSE) ? true : false;
}

Comments

1

It's not possible to marshal a C++ std::string in the way you are attempting. What you really need to do here is write a wrapper function which uses a plain old const char* and converts to a std::string under the hood.

C++

extern C { 
  void OpenWrapper(const WCHAR* pName) {
    std::string name = pName;
    OpenA(name);
  }
}

C#

[DllImport("pk2.dll")]
public static extern void OpenWrapper( [In] string name);

Comments

0

I know this topic is a tad old but for future googlers, this should also work (without using char* in C++)

C#:

public static extern bool OpenA([In, MarshalAs(UnmanagedType.LPStr)] path);

C++:

bool __declspec( dllexport ) OpenA(std::string file);

3 Comments

What do you mean? Did you try the code above and it didn't work?
I mean, is there any reference page which states that it should work, and defines requirements for it to work?
I'm sorry but I can't find the reference for this atm (this was quite a long time ago). However you could try this page: msdn.microsoft.com/en-us/library/s9ts558h%28v=vs.110%29.aspx

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.