开发者

DllImport, Char*& and StringBuilder C/C#

开发者 https://www.devze.com 2023-03-07 06:39 出处:网络
I have a problem, I tried to look at almost all the poster solutions, unsuccessful to find a suitable one.

I have a problem, I tried to look at almost all the poster solutions, unsuccessful to find a suitable one.

The question is easy, Want to have a return string from unmanaged C code in my managed C#. The c function is:

extern "C" __declspec(dllexport) int process_batch (char *&result);

and in C# I imported the DLL:

[DllImport("mydll.dll")]
public static extern IntPtr process_batch(StringBuilder result);

I run, but the return value in my StringBuilder is a 7-8 character string of non-sense! (I think the memory address)

I tried adding ref before the StringBuilder, this time I get the correct return value in StringBuilder but I get AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memor开发者_如何学Goy is corrupt.

So I need your help to fix this.

Just one more thing, I use malloc in c for allocating the memory to the char* variable.

Thanks,


If you really want to do that, pass the parameter as a ref IntPtr, then call Marshal.PtrToStringAnsi, or similar.

[DllImport("mydll.dll")]
public static extern IntPtr process_batch(ref IntPtr result);

Note that, since you're allocating the string with malloc in C, the .NET program will have to keep track of the returned pointer so that it can pass it back to you to be deallocated. Otherwise you'll have a memory leak.

If you were to pass a ref StringBuilder, you wouldn't be able to deallocate the memory that was allocated by the C program.

Also, as somebody commented in another post, you need to set the calling convention:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]


I've been using the following code successfully:

[DllImport("user32.dll", EntryPoint = "GetClassName", ExactSpelling = false,
            CharSet = CharSet.Auto, SetLastError = true)]
private static extern int _GetClassName(IntPtr hwnd, StringBuilder lpClassName,
            int nMaxCount);

public static string GetClassName(IntPtr hWnd)
{
   StringBuilder title = new StringBuilder(MAXTITLE);
   int titleLength = _GetClassName(hWnd, title, title.Capacity + 1);
   title.Length = titleLength;

   return title.ToString();
}

I'd advise for a more specific declaration of the imported method via the DllImportAttribute. Try the CharSet = CharSet.Auto bit for instance

I know that this is not exactly related to your original problem as this makes use of the Windows API, but maybe it is of help nonetheless.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号