Sto cercando di far funzionare Java Access Bridge (2.02) con C# (.NET 3.5). Ho funzionato per alcune funzioni, ma quando chiamo una funzione che fa riferimento a una struct (getAccessibleContextInfo), ottengo questo messaggio di errore: System.AccessViolationException: Tentativo di leggere o scrivere memoria protetta. Questo è spesso un'indicazione che un'altra memoria è corrotta.System.AccessViolationException quando si chiama C++ dll
Ecco il mio codice:
[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");
}
}
non credo che sia un problema con la dll Java, in quanto funziona bene con l'esempio programma C++ che viene fornito con l'API.
Sto indovinando dalla ricerca di Google che si tratta di un problema con il modo in cui sto eseguendo il marshalling della struttura AccessibleContextInfo
, ma non ho idea di come farlo correttamente.
Ecco il modo in cui la struct è dichiarata in "AccessBridgePackages.h" del programma di esempio
#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;
Ogni aiuto è molto apprezzato!
Per quanto posso vedere, potrebbe esserci un problema con le dimensioni dei tipi in .NET e C++, 'BOOL' in C++ ha le dimensioni di un byte, mentre .NET's bool ha la dimensione di 4 byte. Potrebbe essere utile mostrare la definizione del C++. –
L'argomento vmID non è lungo, è int in C#. –