I'm attempting to call the following trivial C function from C#:
SIMPLEDLL_API const char* ReturnString() { return "Returning a static string!"; }
With the following P/Invoke declaration (with or without the return attribute, it makes no difference):
[DllImport("SimpleDll")] [return: MarshalAs(UnmanagedType.LPStr)] public static extern string ReturnString();
It works if the DLL is a Debug build but crashes in a Release build (AccessViolationException).
I am calling over a dozen other simple functions and this is the only one that fails (here are the others:)
[DllImport("SimpleDll")] public static extern int NextInt(); [DllImport("SimpleDll")] public static extern void SetNextInt(int x); [DllImport("SimpleDll")] public static extern int AddInts(int a, int b); [DllImport("SimpleDll")] public static extern int AddFourInts(int a, int b, int c, int d); [DllImport("SimpleDll")] public static extern double AddDoubles(double x, double y); [DllImport("SimpleDll")] public static extern IntPtr AddDoublesIndirect(ref double x, ref double y); [DllImport("SimpleDll")] [return: MarshalAs(UnmanagedType.U1)] public static extern char CharStringArgument([MarshalAs(UnmanagedType.LPStr)]string s); [DllImport("SimpleDll")] [return: MarshalAs(UnmanagedType.U2)] public static extern char WCharStringArgument([MarshalAs(UnmanagedType.LPWStr)]string s); [DllImport("SimpleDll")] [return: MarshalAs(UnmanagedType.LPWStr)] public static extern string ReturnWString(); [DllImport("SimpleDll")] [return: MarshalAs(UnmanagedType.BStr)] public static extern string ReturnBSTR(); [DllImport("SimpleDll")] public static extern System.Drawing.Point MakePoint(int x, int y); [DllImport("SimpleDll")] public static extern IntPtr MakePointIndirect(int x, int y); [DllImport("SimpleDll")] public static extern int GetPointY(System.Drawing.Point p); [DllImport("SimpleDll")] public static extern int GetPointYIndirect(ref System.Drawing.Point pp); [DllImport("SimpleDll")] public static extern int SumIntegers(ref int firstElem, int size);
Strings in C are arrays of char elements, so we can't really return a string - we must return a pointer to the first element of the string. All forms are perfectly valid. Note the use of const , because from the function I'm returning a string literal, a string defined in double quotes, which is a constant.
This is because the function does not return a single character. Instead it returns an address which POINTS to a character (hence the name pointer), and it is denoted by a * .
In C programming language, *p represents the value stored in a pointer and p represents the address of the value, is referred as a pointer. const char* and char const* says that the pointer can point to a constant char and value of char pointed by this pointer cannot be changed.
One solution is to allocate the appropriate amount of memory in the main function, and pass the pointer to the memory to the helper function. Show activity on this post. you shouldn't return data that sits on automatic storage, when you return it goes out of scope. scope and storage duration are two different beasts.
Or maybe try to use
[DllImport("SimpleDll")] public static extern IntPtr ReturnString();
and in your calling code, use the Marshal Class
string ret = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(PInvoke.ReturnString());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With