首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNA与Libvirt c代码。我做错什么了?

JNA与Libvirt c代码。我做错什么了?
EN

Stack Overflow用户
提问于 2020-03-04 13:33:57
回答 1查看 90关注 0票数 0

我是JNA的新手,正在尝试从libvirt c和JNA获取存储信息。

有两个libvirt c函数,virConnectListAllStoragePools()virStoragePoolGetInfo(),如下所示。

代码语言:javascript
复制
    /**
     * virConnectListAllStoragePools:
     * @conn: Pointer to the hypervisor connection.
     * @pools: Pointer to a variable to store the array containing storage pool
     *         objects or NULL if the list is not required (just returns number
     *         of pools).
     * @flags: bitwise-OR of virConnectListAllStoragePoolsFlags.
     *
     * Collect the list of storage pools, and allocate an array to store those
     * objects. This API solves the race inherent between
     * virConnectListStoragePools and virConnectListDefinedStoragePools.
     *
     * Normally, all storage pools are returned; however, @flags can be used to
     * filter the results for a smaller list of targeted pools.  The valid
     * flags are divided into groups, where each group contains bits that
     * describe mutually exclusive attributes of a pool, and where all bits
     * within a group describe all possible pools.
     *
     * The first group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE (online)
     * and VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE (offline) to filter the pools
     * by state.
     *
     * The second group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_PERSITENT
     * (defined) and VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT (running but not
     * defined), to filter the pools by whether they have persistent config or not.
     *
     * The third group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART
     * and VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART, to filter the pools by
     * whether they are marked as autostart or not.
     *
     * The last group of @flags is provided to filter the pools by the types,
     * the flags include:
     * VIR_CONNECT_LIST_STORAGE_POOLS_DIR
     * VIR_CONNECT_LIST_STORAGE_POOLS_FS
     * VIR_CONNECT_LIST_STORAGE_POOLS_NETFS
     * VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL
     * VIR_CONNECT_LIST_STORAGE_POOLS_DISK
     * VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI
     * VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
     * VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
     * VIR_CONNECT_LIST_STORAGE_POOLS_RBD
     * VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
     * VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
     * VIR_CONNECT_LIST_STORAGE_POOLS_ZFS
     * VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE
     * VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT
     *
     * Returns the number of storage pools found or -1 and sets @pools to
     * NULL in case of error.  On success, the array stored into @pools is
     * guaranteed to have an extra allocated element set to NULL but not included
     * in the return count, to make iteration easier.  The caller is responsible
     * for calling virStoragePoolFree() on each array element, then calling
     * free() on @pools.
     */
    int
    virConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)        
    {
    //logic about set pool pointer to parameter '**pools' and return number of pools.
    }

    /**
     * virStoragePoolGetInfo:
     * @pool: pointer to storage pool
     * @info: pointer at which to store info
     *
     * Get volatile information about the storage pool
     * such as free space / usage summary
     *
     * Returns 0 on success, or -1 on failure.
     */
    int
    virStoragePoolGetInfo(virStoragePoolPtr pool,
                          virStoragePoolInfoPtr info)
    {
    // logic about set pool info to parameter 'info'.
    }

我用JNA编写的java代码是:。

1) StoragePoolPointer.java

代码语言:javascript
复制
    import com.sun.jna.PointerType;
    public class StoragePoolPointer extends PointerType {}

2) virStoragePoolInfo

代码语言:javascript
复制
    public class virStoragePoolInfo extends Struture {
       public int state;
       public long capacity;
       public long allocation;
       public long available;
       private static final List<String> filedls = Arrays.asList("state", "capacity", "allocation", "available");

       protected List<String> getFieldOrder() {
          return fields;
       }
    }

3) Libvirt.java接口

代码语言:javascript
复制
    public interface Libvirt extends Library {
       int virConnectListAllStoragePools(ConnectionPoinet VCP, StoragePoolPointer[] pPointers, int flag);

       int virStoragePoolGetInfo(StoragePoolPointer poolPointer, virStoragePoolInfo info);
    }

4) jna测试代码

代码语言:javascript
复制
    public void listAllStoragePools(ConnectionPointer VCP) {
       Libvirt libvirt = (Libvirt) Native.loadLibrary("virt", Libvirt.class);

       StoragePoolPointer[] pPointerArr = new StoragePoolPointer[10];
       int result = livirt.virConnectListAllStoragePools(VCP, pPointerArr, 64);
       // result is fine. i get storage pool count. and also i get StoragePoolPointer object inside array.

       virStoragePoolInfo poolInfo = new virStoragePoolInfo(); 
       libvirt.virStoragePoolGetInfo(pPointerArr[0], poolInfo);
       // when i call libvirt.virStoragePoolGetInfo(). i get a error msg like this. 'libvirt: Storage Driver error : invalid storage pool pointer in virStoragePoolGetInfo.
       //error msg : org.libvirt.LibvirtException: invalid storage pool pointer in virStoragePoolGetInfo.
    }

我想我创建了错误的接口方法virConnectListAllStoragePools(),并且我为'virStoragePoolPtr **pools‘传递了错误的参数。

EN

回答 1

Stack Overflow用户

发布于 2020-03-05 15:42:21

本机数组布局在连续的内存中。在本例中,virStoragePoolPtr **pools是指向数组开头的单个指针;C使用它对指针大小的了解来使用偏移量来查找剩余的元素。

JNA不会将(大多数) Java数组转换为这种本机布局。当它这样做时,它使用明确定义的大小,例如对于像int[]这样的原始数组,或者对于JNA可以计算大小并使用其toArray方法进行分配的Structure数组。

您已经在这里定义了一个Java端数组:

代码语言:javascript
复制
StoragePoolPointer[] pPointerArr = new StoragePoolPointer[10];

但是您还没有分配任何要填充该数组的null对象,因此它只是一个由pPointerArr[i] = new StoragePoolPointer()组成的数组。

有(至少)两种方法可以解决这个问题。一种是使用JNA的Memory类直接分配本机内存,如下所示:

代码语言:javascript
复制
pPointerArr = new Memory(10 * Native.POINTER_SIZE);

在对virConnectListAllStoragePools()的方法调用之后,您将在此缓冲区中拥有指针并可以迭代,例如,当您递增i时,Pointer p = pPointerArr.share(i * Native.POINTER_SIZE)将是每个指针。

或者,您可以定义一个包含指针的Structure,如下所示:

代码语言:javascript
复制
@FieldOrder({ "storagePool" })
public class StoragePoolPointer extends Structure {
    public Pointer storagePool;
}

然后,您可以通过以下方式获得Java数组的便利性和连续的本机内存:

代码语言:javascript
复制
StoragePoolPointer[] pPointerArr = 
    (StoragePoolPointer[]) new StoragePoolPointer().toArray(10);

填充数组后,pPointerArr[i].storagePool将是第i个指针。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60519643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档