Accessing Java Access Bridge from C#

Using PInvoke, I can talk to the Access Bridge and connect to GUI events. When I get an event, I can get at the accessibility information, but when I return from the event handler, I get an AccessViolationException. Here's the code:

[DllImport("WindowsAccessBridge.dll")]

private externstaticvoid Windows_run();

[DllImport("WindowsAccessBridge.dll")]

private externstaticvoid setMouseClickedFP(MouseClickedDelegate fp);

[DllImport("WindowsAccessBridge.dll")]

private externstaticvoid releaseJavaObject(System.Int32 vmID, IntPtr javaObject);

[DllImport("WindowsAccessBridge.dll")]

private externstaticvoid getVersionInfo(System.Int32 vmID, out VersionInfo v);

delegatevoid MouseClickedDelegate(System.Int32 vmID, IntPtr jevent, IntPtr ac);

static MouseClickedDelegate mcd;// so delegate won't get gc'd

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

struct VersionInfo{

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

string VMversion;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

string bridgeJavaClassVersion;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

string bridgeJavaDLLVersion;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

string bridgeWinDLLVersion;

}

privatestatic VersionInfo vi =new VersionInfo();

privatevoid button1_Click(object sender, EventArgs e)

{

Windows_run();

mcd =new MouseClickedDelegate(HandleMouseClicked);

setMouseClickedFP(mcd);

}

staticvoid HandleMouseClicked(System.Int32 vmID, IntPtr jevent, IntPtr ac){

getVersionInfo(vmID, out vi);

releaseJavaObject(vmID, ac);

releaseJavaObject(vmID, jevent);

}

If I put a breakpoint in the event handler, I get the version information just fine, and the releaseJavaObject calls both work. However, if I then continue, I get an AccessViolationException which points back to the Application.Run call in Main.

Strangely, if I define the event handler without parameters, it all works fine, although the event isn't terribly useful that way. This is probably something simple staring me in the face. What am I missing here?

[3293 byte] By [Quotequada] at [2007-11-27 5:15:35]
# 1
It sounds like you need to set the CallingConvention attribute on each DLLImport statement. (to CallingConvention.CDecl)
CiaranGa at 2007-7-12 10:37:53 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for your response. Since the bridge is apparently built with the cdecl calling convention, you are correct that the DiiImport attributes should specify this calling convention, although all the calls work fine without it (I assume I'm leaving stuff on the stack the way things are).

The problem is with the callback for events. It, too, must use the cdecl calling convention, but in .Net 1.1 there is no way to specify that a delegate should do this. .Net 2.0 added a new attribute, that I stumbled upon totally by accident, that allows this. So the solution turns out to be specifying the delegate like this:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

delegate void MouseClickedDelegate(System.Int32 vmID, IntPtr jevent, IntPtr ac);

Quotequada at 2007-7-12 10:37:54 > top of Java-index,Desktop,Core GUI APIs...