Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JNA将Java布尔映射为-1整数?_Java_Jna - Fatal编程技术网

JNA将Java布尔映射为-1整数?

JNA将Java布尔映射为-1整数?,java,jna,Java,Jna,在JNA结构中传递boolean值时,我使用的本机库发出了一个惊人的警告: value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE 在此库中,VK_TRUE和VK_FALSE分别定义为1和0 结构本身并不特别复杂,其他一切似乎都正常工作(本机库似乎将“未定义”布尔值视为false),但无论如何,这里是: public class VkSwapchainCreateInfoKHR extends Structur

在JNA结构中传递
boolean
值时,我使用的本机库发出了一个惊人的警告:

value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE
在此库中,
VK_TRUE
VK_FALSE
分别定义为1和0

结构本身并不特别复杂,其他一切似乎都正常工作(本机库似乎将“未定义”布尔值视为false),但无论如何,这里是:

public class VkSwapchainCreateInfoKHR extends Structure {
    public int sType;
    public Pointer pNext;
    public int flags;
    public Pointer surface;
    public int minImageCount;
    public int imageFormat;
    public int imageColorSpace;
    public VkExtent2D imageExtent;
    public int imageArrayLayers;
    public int imageUsage;
    public int imageSharingMode;
    public int queueFamilyIndexCount;
    public Pointer pQueueFamilyIndices;
    public int preTransform;
    public int compositeAlpha;
    public int presentMode;
    public boolean clipped;       // <--------- this is the field in question
    public Pointer oldSwapchain;
}
公共类VkSwapchainCreateInfoKHR扩展结构{
公共int sType;
公共指针pNext;
公共国旗;
公共指针表面;
公共int最小计数;
公共int图像格式;
公共图像色彩空间;
公共VkExtent2D图像范围;
公共图像阵列专家;
公共用途;
公共图像共享模式;
公共int-queueFamilyIndexCount;
公共指针pquefamilyindice;
公共信息预转换;
公共综合医院;
公共int呈现模式;

公共布尔剪裁;//JNA通过
libffi
映射到本机库。
libffi
中没有
bool
类型,因此必须使用其他映射——JNA选择将
boolean
映射到
ffi\u类型uint32
。这在结构中起作用因为它恰好与32位映射大小匹配,但与定义不匹配:在C中,0为false,任何非零的值都为true。只有当本机类型也是
boolean
时,此0/非零解释才会恢复为false/true

使用
FFI
JNI
boolean
关键字进行web搜索可以发现多个示例,例如,当通过FFI或JNI访问库时,会出现不可预测的结果,并且不符合布尔值的0/1要求。后一个示例与真正的Java
boolean
被解释为值不是1的C
int

在FFI和您的库之间的某个地方,可能在编译的字节码和/或平台/编译器相关的类型转换中,很可能对
0x00000000
应用了按位“not”,将其转换为
0xffffff
,在C中仍然是“true”

底线是,JNA默认情况下会将Java boolean
false
映射为32位本机值0,将Java boolean
true
映射为32位本机值而非0,这就是可以假设的所有内容。如果您的库要求
true
的整数值为1,请使用可以指定的整数类型对
boolean
进行逻辑设置或使用自定义类型映射,为您将
int
设置为0或1。JNA有一个将Windows
BOOL
类型转换为1或0的示例

在本例中,假设您正在映射VkSwapchainCreateInfoKHR结构,
clipped
的类型是VkBool32:

typedef struct VkSwapchainCreateInfoKHR {
    VkStructureType                  sType;
    const void*                      pNext;
    VkSwapchainCreateFlagsKHR        flags;
    VkSurfaceKHR                     surface;
    uint32_t                         minImageCount;
    VkFormat                         imageFormat;
    VkColorSpaceKHR                  imageColorSpace;
    VkExtent2D                       imageExtent;
    uint32_t                         imageArrayLayers;
    VkImageUsageFlags                imageUsage;
    VkSharingMode                    imageSharingMode;
    uint32_t                         queueFamilyIndexCount;
    const uint32_t*                  pQueueFamilyIndices;
    VkSurfaceTransformFlagBitsKHR    preTransform;
    VkCompositeAlphaFlagBitsKHR      compositeAlpha;
    VkPresentModeKHR                 presentMode;
    VkBool32                         clipped;
    VkSwapchainKHR                   oldSwapchain;
} VkSwapchainCreateInfoKHR;
在哪里

typedef uint32_t VkBool32;
因此,
int
是正确的映射——您需要将
clipped
映射到32位整数Edit:正如您在回答中指出的,添加自己的类型映射器以更好地处理这些
int
值非常简单


(当我在查看类型映射时,您可能会发现
IntByReference
对于
pQueueFamilyIndices
字段,映射比
Pointer
更好。)(对于可变长度
int
数组,您的映射是正确的。)

事实上,在各种本机库结构中有很多布尔值,事实上有几百个!最好保留布尔值字段的意图,而不是仅仅因为实现强制了该限制就用
int
替换它们。因此我花了一些时间研究JNA类型转换

当创建本机库时,JNA支持使用作为附加参数传递给
Native::load
TypeMapper
映射自定义类型。自定义类型映射是使用Java到/从本机转换器接口
TypeConverter
定义的

定义一个自定义布尔包装器,用1=true和0=false将Java
boolean
映射到C
int
,这相当简单:

public final class VulkanBoolean {
    static final TypeConverter MAPPER = new TypeConverter() {
        @Override
        public Class<?> nativeType() {
            return Integer.class;
        }

        @Override
        public Object toNative(Object value, ToNativeContext context) {
            if(value == null) {
                return VulkanBoolean.FALSE.toInteger();
            }
            else {
                final VulkanBoolean bool = (VulkanBoolean) value;
                return bool.toInteger();
            }
        }

        @Override
        public Object fromNative(Object nativeValue, FromNativeContext context) {
            if(nativeValue == null) {
                return VulkanBoolean.FALSE;
            }
            else {
                final int value = (int) nativeValue;
                return value == 1 ? VulkanBoolean.TRUE : VulkanBoolean.FALSE;
            }
        }
    };

    public static final VulkanBoolean TRUE = VulkanBoolean(true);
    public static final VulkanBoolean FALSE = VulkanBoolean(false);

    private final boolean value;

    private VulkanBoolean(boolean value) {
        this.value = value;
    }

    public boolean value() {
        return value;
    }

    public int toInteger() {
        return value ? 1 : 0;
    }
}
我使用了相同的机制,将~300个代码生成的枚举自动神奇地映射到本机
int
,当前看起来如下所示:

public enum VkSubgroupFeatureFlag implements IntegerEnumeration {
    VK_SUBGROUP_FEATURE_BASIC_BIT(1),   
    VK_SUBGROUP_FEATURE_VOTE_BIT(2),    
    ...

    private final int value;

    private VkSubgroupFeatureFlag(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return value;
    }
}
目前,引用“枚举”的所有结构实际上都是作为
int
实现的。使用
IntegerEnumeration
的自定义类型转换器,字段类型可以是实际的Java枚举,JNA将处理与整数值之间的转换(我目前必须手动完成)。这显然使结构的类型更加安全,更加清晰,并且明确地引用了实际的枚举,而不是
int
-nice

i、 e

(最近发现了一个这样做的例子)


希望所有这些胡言乱语都能帮助人们了解JNA的变幻莫测。

这里有些可疑之处。我认为正确的代码应该具有布尔字段的实际位模式,而不会进入方程中。布尔值有两种潜在状态…“真”和“假”…句点。那么,发生了什么事正在布尔值和整数值之间进行映射?该结构是否确实包含格式不正确的“true”位模式,或者是否有其他东西将值转换为int,然后另一个东西需要不同的整数表示形式?给定常量定义,代码是否希望该字段为整数值?也许它只需要是一个int。什么本机库定义了VK_TRUE?-这可能是任何数据库定义的函数吗?保存此结构?@Steve No databases,JNA用于调用本机l
public interface Library {
    abstract class VulkanStructure extends Structure {
        protected VulkanStructure() {
            super(VulkanLibrary.TYPE_MAPPER);
        }
    }
...
}

public class VkSwapchainCreateInfoKHR extends VulkanStructure { ... }
public enum VkSubgroupFeatureFlag implements IntegerEnumeration {
    VK_SUBGROUP_FEATURE_BASIC_BIT(1),   
    VK_SUBGROUP_FEATURE_VOTE_BIT(2),    
    ...

    private final int value;

    private VkSubgroupFeatureFlag(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return value;
    }
}
public class VkSwapchainCreateInfoKHR extends VulkanStructure {
    ...
    public int flags;
    public Pointer surface;
    public int minImageCount;
    // The following fields were int but are now the Java enumerations
    public VkFormat imageFormat = VkFormat.VK_FORMAT_UNDEFINED;
    public VkColorSpaceKHR imageColorSpace;
    ...
}