This discussion is archived
5 Replies Latest reply: Mar 17, 2009 1:40 AM by PhHein RSS

Accessing Java Access Bridge from C#

843807 Newbie
Currently Being Moderated
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 extern static void Windows_run();

        [DllImport("WindowsAccessBridge.dll")]
        private extern static void setMouseClickedFP(MouseClickedDelegate fp);

        [DllImport("WindowsAccessBridge.dll")]
        private extern static void releaseJavaObject(System.Int32 vmID, IntPtr javaObject);

        [DllImport("WindowsAccessBridge.dll")]
        private extern static void getVersionInfo(System.Int32 vmID, out VersionInfo v);

        delegate void 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;
        }

        private static VersionInfo vi = new VersionInfo();


        private void button1_Click(object sender, EventArgs e)
        {
            Windows_run();
            mcd = new MouseClickedDelegate(HandleMouseClicked);
            setMouseClickedFP(mcd);
        }

        static void 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?
  • 1. Re: Accessing Java Access Bridge from C#
    843807 Newbie
    Currently Being Moderated
    It sounds like you need to set the CallingConvention attribute on each DLLImport statement. (to CallingConvention.CDecl)
  • 2. Re: Accessing Java Access Bridge from C#
    843807 Newbie
    Currently Being Moderated
    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);
  • 3. Re: Accessing Java Access Bridge from C#
    843807 Newbie
    Currently Being Moderated
    Hi
    Thanks , It worked . But right now I am try to call this function

    #region AccessBridgeVersionInfo
    [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;
    }

    #endregion
    #region AccessibleContextInfo
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct AccessibleContextInfo
    {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
    string name;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
    string description;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    string role;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    string states;
    [MarshalAs(UnmanagedType.I4)]
    int indexInParent;
    [MarshalAs(UnmanagedType.I4)]
    int childrenCount;
    [MarshalAs(UnmanagedType.I4)]
    int x;
    [MarshalAs(UnmanagedType.I4)]
    int y;
    [MarshalAs(UnmanagedType.I4)]
    int width;
    [MarshalAs(UnmanagedType.I4)]
    int height;
    [MarshalAs(UnmanagedType.Bool)]
    bool accessibleComponent;
    [MarshalAs(UnmanagedType.Bool)]
    bool accessibleAction;
    [MarshalAs(UnmanagedType.Bool)]
    bool accessibleSelection;
    [MarshalAs(UnmanagedType.Bool)]
    bool accessibleText;
    [MarshalAs(UnmanagedType.Bool)]
    bool accessibleValue;
    };
    [DllImport("WindowsAccessBridge.dll", CallingConvention = CallingConvention.Cdecl)]
    private extern static bool getAccessibleContextInfo(int vmID, IntPtr ac, out AccessibleContextInfo textInfo);
    [DllImport("WindowsAccessBridge.dll", CallingConvention = CallingConvention.Cdecl)]
    private extern static bool getAccessibleTextItems(int vmID, IntPtr at,out AccessibleTextItemsInfo textItems,int index);
    [DllImport("WindowsAccessBridge.dll", CallingConvention = CallingConvention.Cdecl)]
    private extern static void setMouseClickedFP(MouseClickedDelegate fp);
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate void MouseClickedDelegate(int vmID, IntPtr jevent, IntPtr ac);
    static MouseClickedDelegate m_MouseClickedDelegate;
    static void HandleMouseClicked(int vmID, IntPtr jevent, IntPtr ac)
    {
    getAccessibleContextInfo(vmID, ac, out m_ACI);
    getAccessibleTextItems(vmID, ac, out m_ATII, 0);
    releaseJavaObject(vmID, ac);
    releaseJavaObject(vmID, jevent);
    }
    but when I call getAccessibleContextInfo(vmID, ac, out m_ACI) it gave error of StackOverflow. Please help me. I think
    I could not marshal the struct AccessibleContextInfo properly but could not get help from anywhere else.
  • 4. Re: Accessing Java Access Bridge from C#
    843807 Newbie
    Currently Being Moderated
    AccessibleContextInfo is defined within Java Access Bridge\src\bridge\src\AccessBridgePackages.h

    MAX_STRING_SIZE and SHORT_STRING_SIZE are 1024 and 256 respectively.

    Underneath declaration works for me (Java Access Bridge v 2)
    [StructLayout(LayoutKind.Sequential , CharSet=CharSet.Unicode)]
        public struct AccessibleContextInfo
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public string name;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public string description;
    
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string role;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string role_en_US;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string states;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string states_en_US;
    
            [MarshalAs(UnmanagedType.I4)]
            public int indexInParent;
            [MarshalAs(UnmanagedType.I4)]
            public int childrenCount;
            [MarshalAs(UnmanagedType.I4)]
            public int x;
            [MarshalAs(UnmanagedType.I4)]
            public int y;
            [MarshalAs(UnmanagedType.I4)]
            public int width;
            [MarshalAs(UnmanagedType.I4)]
            public int height;
    
            [MarshalAs(UnmanagedType.Bool)]
            public bool accessibleComponent;
            [MarshalAs(UnmanagedType.Bool)]
            public bool accessibleAction;
            [MarshalAs(UnmanagedType.Bool)]
            public bool accessibleSelection;
            [MarshalAs(UnmanagedType.Bool)]
            public bool accessibleText;
            [MarshalAs(UnmanagedType.Bool)]
            public bool accessibleInterfaces;
        };
  • 5. Re: Accessing Java Access Bridge from C#
    PhHein Guru Moderator
    Currently Being Moderated
    Guys, this thread is years old! I'm locking.