System.AccessViolationException when calling C ++ dll

I am trying to get Java Access Bridge (2.02) to work with C # (.NET 3.5). I have work for some functions, but when I call a function that references struct (getAccessibleContextInfo), I get this error message: System.AccessViolationException: attempt to read or write protected memory. This often indicates that another memory is corrupted.

Here is my code:

[DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] internal extern static void Windows_run(); [DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] private extern static void releaseJavaObject(long vmID, IntPtr javaObject); [DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] private extern static bool isJavaWindow(IntPtr window); [DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] private extern static bool getAccessibleContextInfo(long vmID, IntPtr ac, out AccessibleContextInfo textInfo); [DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool getAccessibleContextFromHWND(IntPtr hwnd, out long vmID, out IntPtr ac); [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; }; private void Form1_Load(object sender, EventArgs e) { Windows_run(); } private void button1_Click(object sender, EventArgs e) { long vmID; IntPtr ac; if (getAccessibleContextFromHWND(mainWindowHwnd, out vmID, out ac)) { MessageBox.Show("Got Context: " + vmID.ToString() + ", " + ac.ToString()); AccessibleContextInfo info; if (getAccessibleContextInfo(vmID, ac, out info)) //this is where the error is thrown { MessageBox.Show("Got Context Info: " + info.name); } else { MessageBox.Show("Getting info failed"); } } else { MessageBox.Show("Accessing failed"); } } 

I donโ€™t think this is a problem with java-dll, as it works fine with the C ++ example program that comes with the API.

I guess from a google search that this is a problem with the way I sort the AccessibleContextInfo structure, but I don't know how to do it correctly.

This is how the structure is declared in the sample program "AccessBridgePackages.h"

 #define MAX_STRING_SIZE 1024 #define SHORT_STRING_SIZE 256 typedef struct AccessibleContextInfoTag { wchar_t name[MAX_STRING_SIZE]; // the AccessibleName of the object wchar_t description[MAX_STRING_SIZE]; // the AccessibleDescription of the object wchar_t role[SHORT_STRING_SIZE]; // localized AccesibleRole string wchar_t role_en_US[SHORT_STRING_SIZE]; // AccesibleRole string in the en_US locale wchar_t states[SHORT_STRING_SIZE]; // localized AccesibleStateSet string (comma separated) wchar_t states_en_US[SHORT_STRING_SIZE]; // AccesibleStateSet string in the en_US locale (comma separated) jint indexInParent; // index of object in parent jint childrenCount; // # of children, if any jint x; // screen coords in pixels jint y; // " jint width; // pixel width of object jint height; // pixel height of object BOOL accessibleComponent; // flags for various additional BOOL accessibleAction; // Java Accessibility interfaces BOOL accessibleSelection; // FALSE if this object doesn't BOOL accessibleText; // implement the additional interface // in question // BOOL accessibleValue; // old BOOL indicating whether AccessibleValue is supported BOOL accessibleInterfaces; // new bitfield containing additional interface flags } AccessibleContextInfo; 

Any help is much appreciated!

+6
source share
1 answer

Typically, AccessViolations indicate that you messed up the PInvoke signature, but it seems like this is generally fine.

I can think of two things that might help:

1: Potentially suspicious use of Charset.Unicode at the structure level.

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct AccessibleContextInfo { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] public string name; ... 

One would expect that CharSet=Unicode in the structure should โ€œextendโ€ to it, but I have seen situations where it does not look like this. You can try specifying CharSet=Unicode for each MarshalAs attribute.

I'm not sure if this will make a difference, given that the standard string sorting from .NET is already Unicode, but it might be worth it.

2: Perhaps try passing the AccessibleContextInfo structure as a ref parameter rather than an out parameter - for example

 [DllImport("Windowsaccessbridge.dll", CallingConvention = CallingConvention.Cdecl)] private extern static bool getAccessibleContextInfo(long vmID, IntPtr ac, ref AccessibleContextInfo textInfo); 

Update: also, as Hans Passant notes in a comment, remember that long in C # is a 64-bit int, whereas in C / C ++ it is 32-bit. Depending on C ++ function declarations, this might be wrong

0
source

Source: https://habr.com/ru/post/888541/


All Articles