2012-04-15 35 views
5

Tôi đang cố gắng sử dụng JNA để truy vấn các quyền có hiệu lực đối với tệp trong Windows. Cuối cùng, tôi có kế hoạch sử dụng GetEffectiveRightsFromAcl function, nhưng để làm như vậy, tôi cần phải cung cấp một con trỏ đến một số TRUSTEE structure được điền. Nền tảng JNA (platform.jar) không xuất hiện xác định cấu trúc này, vì vậy tôi đang cố gắng tự định nghĩa nó. Dưới đây là những gì tôi có cho đến nay:Chuyển đổi chuỗi thành con trỏ cho JNA

public static class TRUSTEE extends Structure { 
    public TRUSTEE() { 
     super(); 
    } 
    public TRUSTEE(Pointer p) { 
     super(p); 
     read(); 
    } 

    public Pointer pMultipleTrustee; 
    public int MultipleTrusteeOperation; 
    public int TrusteeForm; 
    public int TrusteeType; 
    public Pointer ptstrName; 
} 

Tôi đang cố gắng để cư cấu trúc như thế này:

private TRUSTEE createTrusteeForCurrentUser() { 
    TRUSTEE result = new TRUSTEE(); 
    result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME; 
    result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER; 

    String strName = "CURRENT_USER"; 
    // How can I set result.ptstrName using strName? 
} 

This Google Groups thread khuyến cáo sử dụng String trường trong cấu trúc khi một char * được gọi là cho. Tuy nhiên, tôi không nghĩ điều này là phù hợp trong trường hợp của tôi, xem xét trường ptstrName được phép trỏ đến các loại nội dung khác nhau, tùy thuộc vào giá trị của TrusteeForm. Vì vậy, tôi nghĩ rằng bằng cách nào đó tôi cần phải chuyển đổi từ String thành Pointer thay thế. Tôi tìm thấy các lớp học NativeString trong JNA, mà sẽ làm việc, ngoại trừ đó là một lớp gói riêng.

Cách được khuyến nghị để chuyển đổi Java String thành định dạng gốc và nhận được Pointer cho nó là gì? Tôi thậm chí có sử dụng đúng kiểu dữ liệu cho cấu trúc TRUSTEE không? Tôi hơi mới với JNA, vì vậy xin vui lòng tha thứ cho tôi nếu tôi đang thiếu một cái gì đó hiển nhiên.

Cập nhật

Tôi tìm thấy một giải pháp cho vấn đề của tôi, nhưng nếu có ai có một giải pháp tốt hơn tôi vẫn muốn nghe nó.

Trả lời

2

Tôi giải quyết được sự cố bằng cách sao chép mã nguồn cho gói riêng tư NativeString lớp và tạo bản sao công khai trong dự án của tôi. Tôi đã phải thực hiện một thay đổi nhỏ do việc sử dụng một phương pháp gói-tư nhân trong constructor.

Cập nhật: Khi @fragorl ghi chú trong các nhận xét, việc triển khai NativeString được hiển thị bên dưới bây giờ khá lạc hậu.


Cách sử dụng:

private static TRUSTEE createTrusteeForCurrentUser() { 
    TRUSTEE result = new TRUSTEE(); 
    result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME; 
    result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER; 
    result.ptstrName = new NativeString("CURRENT_USER",true).getPointer(); 
    result.write(); 
    return result; 
} 

NativeString.java:

/** Provides a temporary allocation of an immutable C string 
* (<code>const char*</code> or <code>const wchar_t*</code>) for use when 
* converting a Java String into a native memory function argument. 
* 
* @author Todd Fast, [email protected] 
* @author [email protected] 
*/ 
public class NativeString implements CharSequence, Comparable { 

    private Pointer pointer; 
    private boolean wide; 

    /** Create a native string (NUL-terminated array of <code>char</code>).<p> 
    * If the system property <code>jna.encoding</code> is set, its value will 
    * be used to encode the native string. If not set or if the encoding 
    * is unavailable, the default platform encoding will be used. 
    */ 
    public NativeString(String string) { 
     this(string, false); 
    } 

    /** Create a native string as a NUL-terminated array of <code>wchar_t</code> 
    * (if <code>wide</code> is true) or <code>char</code>.<p> 
    * If the system property <code>jna.encoding</code> is set, its value will 
    * be used to encode the native <code>char</code>string. 
    * If not set or if the encoding is unavailable, the default platform 
    * encoding will be used. 
    * 
    * @param string value to write to native memory 
    * @param wide whether to store the String as <code>wchar_t</code> 
    */ 
    public NativeString(String string, boolean wide) { 
     if (string == null) { 
      throw new NullPointerException("String must not be null"); 
     } 
     // Allocate the memory to hold the string. Note, we have to 
     // make this 1 element longer in order to accommodate the terminating 
     // NUL (which is generated in Pointer.setString()). 
     this.wide = wide; 
     if (wide) { 
      int len = (string.length() + 1) * Native.WCHAR_SIZE; 
      pointer = new Memory(len); 
      pointer.setString(0, string, true); 
     } 
     else { 
      byte[] data = Native.toByteArray(string); 
      pointer = new Memory(data.length + 1); 
      pointer.write(0, data, 0, data.length); 
      pointer.setByte(data.length, (byte)0); 
     } 
    } 

    public int hashCode() { 
     return toString().hashCode(); 
    } 

    public boolean equals(Object other) { 

     if (other instanceof CharSequence) { 
      return compareTo(other) == 0; 
     } 
     return false; 
    } 

    public String toString() { 
     String s = wide ? "const wchar_t*" : "const char*"; 
     s += "(" + pointer.getString(0, wide) + ")"; 
     return s; 
    } 

    public Pointer getPointer() { 
     return pointer; 
    } 

    public char charAt(int index) { 
     return toString().charAt(index); 
    } 

    public int length() { 
     return toString().length(); 
    } 

    public CharSequence subSequence(int start, int end) { 
     return CharBuffer.wrap(toString()).subSequence(start, end); 
    } 

    public int compareTo(Object other) { 

     if (other == null) 
      return 1; 

     return toString().compareTo(other.toString()); 
    } 
} 
+0

Cảm ơn, điều này có vẻ là cách "đúng" để thực hiện. Một câu hỏi - tại sao bạn không sử dụng 1-arg NativeString constructor, thay vì 2 arg? – fragorl

+0

@fragorl Đối với ứng dụng của tôi, tôi đã sử dụng các chuỗi ký tự rộng (Unicode), vì vậy tôi cần thiết lập tham số 'wide' thành' true'. Nhà xây dựng 1-arg đặt nó thành 'false'. –

+0

Ahh xấu của tôi, tôi đã nhìn vào phiên bản mới nhất của jna, nơi họ thay đổi 1-arg constructor. Nó bây giờ đọc: này (chuỗi, Native.getDefaultStringEncoding()) ;. Nhưng bạn đã có mã nguồn cho một phiên bản cũ hơn - tất nhiên, bài đăng của bạn là từ năm 2012, các vòng lặp>< – fragorl

0

thử sử dụng lớp Con trỏ trong http://jna.java.net/javadoc/com/sun/jna/Pointer.html.

+0

Tôi biết tôi cần một 'Pointer', tôi đoán câu hỏi được thêm làm thế nào để chuyển đổi một Java 'chuỗi' sang một định dạng có nguồn gốc và có được một' Pointer' đối tượng với nó. –

9

Giả sử bạn muốn char * ở bên mẹ đẻ (bạn có thể cần nhiều bộ nhớ phân bổ nếu chuỗi chứa ký tự khác ASCII),

String myString = "CURRENT_USER"; 
Pointer m = new Memory(myString.length() + 1); // WARNING: assumes ascii-only string 
m.setString(0, myString); 

Sau đó, bạn có thể sử dụng m bất cứ nơi nào bạn cần tham chiếu chuỗi "gốc".

Đối với chuỗi rộng (wchar_t *),

String myString = "CURRENT_USER"; 
Pointer m = new Memory(Native.WCHAR_SIZE * (myString.length() + 1)); 
m.setWideString(0, myString); 
+0

setString (bù đắp, giá trị) gọi setString (offset, value, Native.getDefaultStringEncoding()). Có vẻ như không an toàn khi giả sử Native.getDefaultStringEncoding() luôn trả về một định dạng chỉ sử dụng 1 byte cho mỗi ký tự, đó là những gì bạn phân bổ? – fragorl

+0

Bạn chính xác, câu trả lời được cập nhật một cách thích hợp. – technomage

+0

Con trỏ m = Bộ nhớ mới (Native.WCHAR_SIZE * (myString.length() + 1); thiếu khung, đây có phải là Pointer m = new Memory (Native.WCHAR_SIZE * (myString.length)) + 1)); ? – fragorl

Các vấn đề liên quan