Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a string from an unmanaged c++ dll to c# [duplicate]

I'm trying to call unmanaged c++ from c# but receiving an exception about the return value. The exception:

System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'return value': Invalid managed/unmanaged type combination (Arrays can only be marshaled as LPArray, ByValArray, or SafeArray).'

I have a similar function that look the same without the return value (void) that do work without any problems.

I set the platform (compiler) of the c++ project to be v100 (Visual Studio 2010) and use .net 4.5 at the c# project.

The c++ project created a lib+dll files that I put both at the executable folder.

When I try to replace the return value to be "String" at the c# code, the exception converted to be:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

When I remove the return value function property ([return: MarshalAs(UnmanagedType.BStr)]) I receive the following exception:

System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'return value': Invalid managed/unmanaged type combination.'

And when I do the combination of: removing the return value function property and converting the return type to string, the application just close itself without catch any exception.

C++ code

extern "C"
{
    ExternalDll_API char* FuncA(char* projectId);
}

ExternalDll_API char* FuncA(char* projectId)
{
    return "abc";
}

C# code

[DllImport("ExternalDll.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern char[] FuncA(string projectId);

var key = FuncA(projectId.ToString());
like image 645
as2005 Avatar asked Dec 24 '22 13:12

as2005


1 Answers

To receive a null terminated string from a C++ dll you can do this:

1-Change the return type to IntPtr:

[DllImport("ExternalDll.dll")]
public static extern IntPtr FuncA(string projectId);

2-Retrieve the string from the pointer using Marshal:

var result = FuncA(someString);
var strResult = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(result);
like image 116
Gusman Avatar answered Feb 26 '23 18:02

Gusman