2011-05-19 7 views
6

C# (.NET 3.5) ile çalışmak için Java Access Bridge (2.02) almaya çalışıyorum. Bazı işlevler için çalışıyorum, ancak bir struct (getAccessibleContextInfo) başvuran bir işlevi çağırdığımda, şu hata iletisini alıyorum: System.AccessViolationException: Korumalı belleği okumaya veya yazmaya çalıştım. Bu genellikle diğer hafızanın bozuk olduğunun bir göstergesidir. o API ile geliyor örneğin C++ programı ile çalışıyor olarakSystem.AccessViolationException

[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"); 
} 
} 

Ben, bu java dll ile ilgili bir sorun olduğunu sanmıyorum:

İşte benim kodudur.

Google aramadan tahmin ediyorum, bu, AccessibleContextInfo yapısını sıraya koyma yöntemiyle ilgili bir sorun, ancak doğru şekilde nasıl yapılacağına dair bir ipucum yok.

İşte Herhangi bir yardım çok takdir edilir yapı örnek programın "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; 

deklare edilmediği yoldur!

+0

Görebildiğim kadarıyla, .NET ve C++ türünde boyutlarla ilgili bir sorun olabilir, C++ 'da BOOL, bir bayt boyutuna sahipken .NET'in bool'udur. 4 bayt büyüklüğünde. C++ tanımını göstererek yardımcı olabilir. –

+0

vmID bağımsız değişkeni uzun değil, int # C dilinde. –

cevap

0

Normalde AccessViolations, PInvoke imzasını bozduğunuzu gösterir, ancak genelde sorun değil gibi görünüyor.

denemek için iki şey düsünebilirz may yardım

1: struct düzeyinde Charset.Unicode ait Potansiyel şüpheli kullanım.

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

biri beklediğinizden o 's üyelerine "yaymak" gerektiği yapı üzerinde CharSet=Unicode, ama bunu yapmak görünmüyor durumları gördük. Her dizenin MarshalAs özniteliğinde CharSet=Unicode belirtmeyi deneyebilirsiniz.

.NET'ten dizelerin varsayılan sıralamasının zaten Unicode olduğu göz önüne alındığında, bunun bir fark yaratıp yaratmayacağından emin değilim, ancak bu bir çekim değerinde olabilir.

2: Belki bir out parametresi yerine bir ref parametre olarak AccessibleContextInfo yapı geçirerek deneyin - örneğin

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

Güncelleme: Ayrıca, Hans Passant yorumunda belirttiği gibi, içinde long hatırlamak C# bir 64 bit int, C/C++ 'da ise 32-bit. C++ işlev bildirimlerine bağlı olarak, bu yanlış olabilir