Yes it is true that the only return type allowed is an int, but you can use that to return a pointer to a string
Managed code:
Code:
using System.Runtime.InteropServices;
public class TestClass
{
[DllImport("kernel32")]
static extern IntPtr GetProcessHeap();
[DllImport("kernel32")]
static extern IntPtr HeapAlloc(IntPtr hHeap, HeapAllocFlags flags, int size);
[Flags]
public enum HeapAllocFlags
{
HEAP_NO_SERIALIZE = 0x00000001,
HEAP_GENERATE_EXCEPTIONS = 0x00000004,
HEAP_ZERO_MEMORY = 0x00000008,
}
public static int TestFunc(string args)
{
try
{
IntPtr Heap, StringMemory;
string ret = "Passed argument string was: " + args;
// Get a handle to the default heap
if ((Heap = GetProcessHeap()) == IntPtr.Zero)
throw new InvalidOperationException("GetProcessHeap() failed");
// Unicode string 2 bytes per character, plus terminating NULL char
int MemSize = ret.Length * 2 + 1;
// Allocate new memory on the heap
if((StringMemory = HeapAlloc(Heap, HeapAllocFlags.HEAP_ZERO_MEMORY, MemSize)) == IntPtr.Zero)
throw new OutOfMemoryException("HeapAlloc() failed to allocate " + MemSize + " bytes.");
// Copy the string to unmanaged memory
Marshal.Copy(ret.ToCharArray(), 0, StringMemory, ret.Length);
// Return a pointer to our memory block
return (int)StringMemory;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return 0;
}
}
Unmanaged code:
Code:
DWORD dwRet = 0;
if(FAILED(CallManagedFunc(L"Managed.TestClass", L"TestFunc", L"1234567890", &dwRet)))
OutputDebugString(L"CallManagedFunc() failed.\n");
if(dwRet)
{
MessageBoxW(NULL, (TCHAR*)dwRet, L"!", MB_OK);
// Free our memory to avoid memory leaks
HeapFree(GetProcessHeap(), 0, (LPVOID)dwRet);
}
See
GetProcessHeap Function (Windows)
HeapAlloc Function (Windows)
HeapFree Function (Windows)
for reference
Edit:
Forgot to include the CallManagedFunc function. Although it's just a wrapper for ExecuteInDefaultAppDomain I'm adding it for completeness
Code:
HRESULT CallManagedFunc(LPCWSTR className, LPCWSTR funcName, LPCWSTR args, DWORD* dwRet)
{
return g_ClrHost->ExecuteInDefaultAppDomain(
g_PathToDLL,
className,
funcName,
args,
dwRet);
}