2012-04-15 3 views
5

JNA를 사용하여 Windows에서 파일의 유효 사용 권한을 쿼리하려고합니다. 궁극적으로는 GetEffectiveRightsFromAcl function을 사용할 계획이지만 그렇게하려면 채워진 TRUSTEE structure에 대한 포인터를 제공해야합니다. JNA 플랫폼 (platform.jar)은이 구조체를 정의한 것처럼 보이지 않으므로 직접 정의하려고합니다. 나는이 같은 구조를 채울려고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; 
} 

: 여기에 지금까지 가지고 무엇

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 threadchar *이 요구 될 때 구조에 String 필드를 사용하는 것이 좋습니다. 그러나 TrusteeForm의 값에 따라 ptstrName 필드가 여러 가지 유형의 항목을 가리킬 수 있으므로이 방법이 내 상황에서는 적절하지 않다고 생각합니다. 그래서 나는 어떻게 든 String에서 Pointer으로 변환해야한다고 생각합니다. JNA에서 NativeString 클래스를 발견했습니다. 이는 패키지 개인 클래스를 제외하고는 작동합니다.

Java String을 기본 형식으로 변환하고 Pointer을 얻으려면 어떻게하는 것이 좋습니까? 구조체 TRUSTEE에 올바른 데이터 형식을 사용하고 있습니까? 나는 JNA에게 약간 새로운 편이어서 뭔가 분명하지 않은 점이 있으면 실례합니다.

업데이트

나는 내 문제에 대한 해결책을 찾았지만 사람이 더 나은 솔루션이 있다면 나는 아직도 그것을 듣고 싶습니다.

답변

2

package-private NativeString 클래스의 소스 코드를 복사하고 프로젝트에서 공용 복사본을 만들어 문제를 해결했습니다. 생성자에서 package-private 메서드를 사용하기 때문에 약간의 변경을해야했습니다.

업데이트 : @fragorl은 주석에 주석을 달았으므로 아래에 표시된 NativeString의 구현은 현재 상당히 오래된 것입니다.


사용법 :

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

감사합니다.이 방법은 올바른 방법입니다. 한 가지 질문 - 왜 2-arg one 대신에 1-arg NativeString 생성자를 사용하지 않았습니까? – fragorl

+0

@fragorl 제 응용 프로그램에서 와이드 문자 (유니 코드) 문자열을 사용하고 있었기 때문에'wide' 매개 변수를'true'로 설정해야했습니다. 1-arg 생성자는이를 'false'로 설정합니다. –

+0

Ahh, 나는 jna의 최신 버전을보고 있었는데, 그들은 1-arg 생성자를 변경했다. 이제 읽습니다. this (string, Native.getDefaultStringEncoding()) ;. 그러나 여기에는 이전 버전의 소스 코드가 있습니다. 물론 2012 년 게시물이 있습니다. < – fragorl

0

http://jna.java.net/javadoc/com/sun/jna/Pointer.html에서 포인터 클래스를 사용해보세요.

+0

나는 질문이'Pointer'을 기본 형식으로 자바'String'을 변환 얻는 방법을 더 생각, 나는'Pointer'을 필요로 알고 그것에 반대하십시오. –

9

네이티브 측면에 char *을 원하는 가정 (문자열이 ASCII 문자가 아닌 문자가 포함 된 경우 당신은 할당 된 메모리를해야 할 수도 있습니다),

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

그런 다음 "네이티브"문자열을 참조해야하는 곳이면 m을 사용할 수 있습니다. 와이드 문자열 (wchar_t *)에 대한

,

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

setString (offset, value)은 setString (offset, value, Native.getDefaultStringEncoding())을 호출합니다. Native.getDefaultStringEncoding()이 할당하는 문자 당 1 바이트 만 사용하는 형식을 항상 반환한다고 가정하는 것은 안전하지 않은 것 같습니다. – fragorl

+0

당신이 정확하고 대답이 적절하게 수정되었습니다. – technomage

+0

포인터 m = 새로운 메모리 (Native.WCHAR_SIZE * (myString.length() + 1); 는 브래킷 누락 (이 포인터 m = 새로운 메모리 (Native.WCHAR_SIZE * (myString.length 것으로 의미) + 1)), ? – fragorl