2011-05-19 175 views
6

Java Access Bridge(2.02)をC#(.NET 3.5)で動作させようとしています。私はいくつかの関数のために働いていますが、構造体(getAccessibleContextInfo)を参照する関数を呼び出すと、このエラーメッセージが表示されます。 System.AccessViolationException:保護されたメモリを読み書きしようとしました。これはしばしば、他のメモリが壊れていることを示します。ここでC++ dllを呼び出すときにSystem.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"); 
} 
} 

それはAPIが付属していますたとえばC++プログラムで正常に動作として、私は、それがJavaのDLLでの問題はないと思います。

私は構造体をマーシャリングする方法に問題があるとGoogleから推測しています。AccessibleContextInfoしかし、正しく行う方法についての手がかりはありません。

は、ここですべてのヘルプははるかに高く評価された構造体は、サンプルプログラムの「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; 

で宣言されている方法です!

+0

私が見る限り、.NETとC++の型サイズに問題があるかもしれません.C++の 'BOOL'はバイトの大きさを持っていますが、.NETのbool 4バイトのサイズを有する。 C++の定義を表示すると役立つかもしれません。 –

+0

vmID引数が長くない、C#でintです。 –

答えて

0

通常のアクセス違反は、PInvoke署名がうまくいかなかったことを示していますが、通常はOKのようです。

は私がしようとする二つのことを考えることができるかもしれないヘルプ

1:構造体レベルでのCharset.Unicode潜在的に疑わしい使用。

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

一つの構造体にCharSet=Unicodeはそれのメンバーに「伝播」必要があることを期待するかもしれないが、私はこれを行うには表示されません。状況を見てきました。 各文字列のMarshalAs属性にCharSet=Unicodeと指定してみることもできます。

.NETの文字列の既定のマーシャリングが既にUnicodeであることを考えれば、これは違いがあるのか​​どうかはわかりませんが、それは価値があるかもしれません。

2:おそらくrefパラメータではなくoutパラメータとしてAccessibleContextInfo構造体を渡してみてください - 例えば

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

更新:ハンスアンパッサンはコメントで指摘しても、long中を覚えていますC#は64ビット intですが、C/C++では32ビットです。 C++の関数宣言によって、それは間違っている可能性があります

関連する問題