Sunday, March 07, 2010

IronPython and callback delegates with 'out' or 'ref' parameters -- the obvious way doesn't work

The actual how-to is given here.

The only on-line documentation I could find that mentioned this has a

TODO - Delegates with out/ref parameters

about halfway down.

So, experiment time. Build callback.dll containing (or the same with 'out'):

namespace Callback
{
using System;
public delegate IntPtr Hook(ref bool handled);
public static class Callback
{
public static object[] MakeCallback(Hook callback)
{
bool handled = false;
IntPtr handle = callback(ref handled);
return new object[] { handle, handled };
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

and call it from IronPython 2.6:

import clr
clr.AddReferenceToFile('Callback.dll')
from Callback import *
from System import IntPtr
def callback(x):
x = True
return IntPtr(42)
test = Callback.MakeCallback(callback)
print test
view raw gistfile1.py hosted with ❤ by GitHub

which yields

Array[object]((<System.IntPtr object at 0x000000000000002B [42]>, False))

In sum -- it fails silently; the direct return value is fine, but mutating the actually by-value parameter does nothing.

Replacing the bool with int, and using non-default values shows that the value of a ref parameter is passed in correctly, it just can't be passed out with direct assignment.

No comments :