0

In my C++ dll named "scandll.dll" I have the following function

extern "C" __declspec(dllexport) void scanfile(char * returnstring)
{
    strcpy(returnstring, "return string");
}

in my C# code I'm doing this

[DllImport("scandll.dll", CharSet = CharSet.Ansi, SetLastError = true )]
public static extern int scanfile(ref IntPtr strReturn);

and this is the method that I'm using to get the value from the dll

public void Scan()
{
     string filename = "";
     IntPtr ptr = new IntPtr();
     scanfile(ref ptr);//Here i get the error
     filename = Marshal.PtrToStringAnsi(ptr);
}

I get an exception thrown as "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

I'm following this link

Calling C++ code from C# error using references in c++ ref in c#

Any help would be appreciated.

Thanks

Community
  • 1
  • 1
Vikneshwar
  • 1,029
  • 4
  • 20
  • 38
  • 1
    Your C function is already wrong. Why do you need to have a C function when you have problems writing one? Can't you use a managed function? – nvoigt Nov 22 '13 at 12:56
  • Setting `CharSet.Ansi` does nothing when you're manually marshaling strings. In fact in this particular case it might slow down the call because the runtime would look for `scanfileA` before looking for `scanfile` – Mgetz Nov 22 '13 at 12:58
  • @nvoigt that dll is further linked with other c++ dll's. I found it the better way to go with this method. – Vikneshwar Nov 22 '13 at 13:18
  • @Vikneshwar if you are really using that link as a guide, you are missing the `&` that makes it a reference in C++. Look at / re-read the [accepted answer](http://stackoverflow.com/a/10682197/1441). – crashmstr Nov 22 '13 at 13:22

2 Answers2

4

Your C++ code is wrong - all it's doing is changing the value of the pointer which has been passed to it to point to a constant string. The caller knows nothing about that change.

It's the same as if you'd done this:

void MyCfunction(int number)
{
   number = 3;
}

and then hoped that a caller of that function would somehow see the number '3' anywhere.

You could do something like this in C++:

void MyCFunction(char* pReturnString)
{
 strcpy(pReturnString, "Hello, world");
}

but you also need to make sure on the C# side that you had provided a buffer with pReturnString pointing to it. One way to do this by using a StringBuilder, and then having your C# declaration of the C function take a parameter like this:

[MarshalAs(UnmanagedType.LPStr)] StringBuilder returnString

You need to reserve space in the StringBuilder before calling into the C++ function.

In real life, C/C++ functions like this pretty much always take an additional length parameter, which allows the caller to tell the callee the maximum length of string it's allowed to copy into the buffer. There is no consistency of convention about whether the length includes the terminating \0 or not, so people are often careful about running right up to the end of the buffer.

Will Dean
  • 39,055
  • 11
  • 90
  • 118
0
  memcpy (  destination,  * source, size_t num );

Try this to assign the value to returnstring = "rturn name";

Vinay Shukla
  • 1,818
  • 13
  • 41