0

I am new to C++.

And I am developing a just simple dll.

I have to C++ function from C# with a file location information which should be string.

And C++ returns some string to C#.

Here are my codes..

extern "C" __declspec(dllexport) const char* ParseData(char *filePath)
{
    string _retValue(filePath);

    printf(_retValue.c_str());  //--> this prints ok

    return _retValue.c_str();
}






[DllImport("D:\\Temp\\chelper.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr ParseData(string s);


static void Main(string[] args)
{
    string s    = "D:\\Temp\\test.bin";
    string ret  = Marshal.PtrToStringAnsi(ParseData(s));
    Console.WriteLine(ret);
}

When I look into the string that C++ returns, it looks like below.

硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼

I am expecting "D:\Temp\test.bin" which I passed to C++ dll.

What's wrong with my code?

Joshua Son
  • 1,839
  • 6
  • 31
  • 51
  • 2
    Your problem is that you're trying to return a local variable. Your DLL has access to that memory because it declared the variable, but the C# program can't access it so it's getting garbage instead. Look into how the Windows API does it: have the caller pass you a buffer and the size of that buffer, and store your results there instead. – cf- Mar 05 '14 at 02:02
  • This could help: http://stackoverflow.com/questions/5298268/returning-a-string-from-pinvoke – thepirat000 Mar 05 '14 at 04:49
  • @thepirat000 Thanks. I solved problem coz of that url. – Joshua Son Mar 05 '14 at 07:20

1 Answers1

0

Your problem is that you're trying to return a local variable. Your DLL has access to that memory because it declared the variable, but the C# program can't access it so it's getting garbage instead. Look into how the Windows API does it: have the caller pass you a buffer and the size of that buffer, and store your results there instead. Something like this (untested):

extern "C" __declspec(dllexport) void ParseData(char* filePath, int pathSize)
{
  char workingPath[pathSize + 1]; //leave space for a trailing null

  strncpy(workingPath, filePath, pathSize);

  //do whatever parsing you need to do here

  strncpy(filePath, workingPath, pathSize);
}

Or just work directly with the passed filePath buffer. But however you choose to do it, make sure you're writing your final result into the buffer you got from the caller, not a local variable.

cf-
  • 8,598
  • 9
  • 36
  • 58
  • Did you mean to return workingPath in c++? It gives me another junk characters like 붹5. – Joshua Son Mar 05 '14 at 02:23
  • No, you shouldn't return workingPath. The caller is supposed to provide you a buffer and the size of that buffer, and then you need to put your return value *only in that buffer*. Trying to return local variables from a DLL will set you up for trouble, because the caller can't access that memory. – cf- Mar 05 '14 at 02:25