JNA通过引用传递String到dll但不返回

时间:2015-03-20 08:47:24

标签: java dll reference jna

嗨我有java和dll的问题。

我需要通过引用将字符串值传递给dll,但是它没有成功。

public short ReadData(int block_id, int offset, int data_size,StringByReference dataBuf, IntByReference err_code);

问题是StringByReference dataBuf,我尝试了很多方法来找到解决方案,但它不起作用。

通话功能是:

ReadData(0, 4, 13, ??? , status);

因为它没有.dll文件。

功能

`public static short Read_Data(int card_type, int block_id, int offset, int data_size, String dataBuf, IntByReference err_code){
        short rc;
        IntByReference status = new IntByReference(0);
         int len = data_size+16;
        //StringByReference dataBuf_ref =  new StringByReference( spaces(data_size+16));
        //StringBuilder zText = new StringBuilder ();
        //zText.append(dataBuf);
        dataBuf = spaces(data_size+16);
        //StringByReference a = new StringByReference(dataBuf);
    //  StringByReference a = new StringByReference(dataBuf);

    //Pointer ppp =  new Memory(dataBuf.length()+1);
    //ppp.setByte(len, dataBuf.getBytes()[0]);
    //PointerByReference p = new PointerByReference(ppp);


    //Pointer pp = null ;
    //pp.setString(len, dataBuf);
    //p.setValue(a.getPointer());
    StringBuffer_REF z = new StringBuffer_REF(dataBuf);

    //byte[] b = dataBuf.getBytes(); 
    //Memory m = new Memory(len+1);
    //m.write(0, b, 0, len);




    System.out.println("Read_Data");

    System.out.println("status "+status.getValue());




    rc = s_ope.ReadData(block_id, offset, data_size,?????, status); /// HERE NEED HELP
//  System.out.println("dataBuf_ref"+ a.getValue().replace(" ", "*"));

    if(rc != 0){
        System.out.println("Err Read_Data : "+rc+" - "+status.getValue());
    }
    err_code = status;
    return rc;
}`

4 个答案:

答案 0 :(得分:4)

我在this网站上找到了您的问题的答案。只需创建新的StringByReference java类型,它应该可以工作。

// This is a class that facilitates passing a String by reference to
// C library routines so that the string  may be modified by the C
// routine and the modifications is reflected on JAVA side as well
// Save this in a file StringByReference.java in current directory

import com.sun.jna.ptr.ByReference;

public class StringByReference extends ByReference {
    public StringByReference() {
        this(0);
    }

    public StringByReference(int size) {
        super(size < 4 ? 4 : size);
        getPointer().clear(size < 4 ? 4 : size);
    }

    public StringByReference(String str) {
        super(str.length() < 4 ? 4 : str.length() + 1);
        setValue(str);
    }

    private void setValue(String str) {
        getPointer().setString(0, str);
    }

    public String getValue() {
        return getPointer().getString(0);
    }
}

答案 1 :(得分:0)

我尝试做其他方式。所以我最终需要使用byte []并使用intbyreference来帮助将java中的int值转换为vb。

答案 2 :(得分:0)

如果有人仍然需要这个,只需使用String[] result = new String[1]并将其传递给本机函数。 JNA将结果转换为此数组,结果将显示在result[0]

答案 3 :(得分:0)

在可以找到的许多解决方案中,只有在找到另一种使用Memory类的方法之前,没人能奏效(在大多数情况下,我是垃圾或崩溃)。我的用例是一个C方法,该方法通过参数返回UTF-16字符串,而调用方拥有所有权:

SHARED_API int GetString(char16_t** str)
{
    *str = (char16_t *)malloc(sizeof(u"Hello"));
    memcpy(*str, u"Hello", sizeof(u"Hello"));
    return 0;
}

然后我创建了以下课程:

import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.platform.win32.*;

public final class StringByReference extends Memory
{
    private static boolean IsWindows;

    static
    {
        IsWindows = System.getProperty("os.name").startsWith("Windows");
    }

    public StringByReference()
    {
        super(Native.POINTER_SIZE);
    }

    @Override
    public void finalize()
    {
        // Free the pointer since caller has ownership
        Pointer pointer = getPointer(0);
        if (IsWindows)
            Ole32.INSTANCE.CoTaskMemFree(pointer);
        else
            Native.free(Pointer.nativeValue(pointer));
        super.finalize();
    }

    @Override
    public String toString()
    {
        return getPointer(0).getWideString(0);
    }
}

可以通过具有正确签名并接受Library的{​​{1}}对象以下列方式使用它:

StringByReference