JNA maps Java boolean to -1 integer?Is Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?What is the difference between public, protected, package-private and private in Java?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?How do I determine whether an array contains a particular value in Java?How do I convert a String to an int in Java?Creating a memory leak with Java

Is there a reason why Turkey took the Balkan territories of the Ottoman Empire, instead of Greece or another of the Balkan states?

Can I use LPGL3 for library and Apache 2 for "main()"?

Did any early RISC OS precursor run on the BBC Micro?

Why did Dr. Strange keep looking into the future after the snap?

In a series of books, what happens after the coming of age?

If quadruped mammals evolve to become bipedal will their breast or nipple change position?

What does the copyright in a dissertation protect exactly?

Can the attacker of a Sanctuary'd target choose not to attack anyone else?

Assuming a normal distribution: what is the sd for a given mean?

What happened to the British convicts transported to America after the American Revolution?

why it is 2>&1 and not 2>>&1 to append to a log file

What is meant by 実感が欠けていく here?

Clauses with 3 infinitives at the end

cd ` command meaning and how to exit it?

Did each Kohen Gadol wear his predecessor's garments?

What does “two-bit (jerk)” mean?

What detail can Hubble see on Mars?

When does WordPress.org notify sites of new version?

Is it safe to keep the GPU on 100% utilization for a very long time?

Justification of physical currency in an interstellar civilization?

Select list elements based on other list

Why did Gendry call himself Gendry Rivers?

I want to write a blog post building upon someone else's paper, how can I properly cite/credit them?

Can anyone identify this unknown 1988 PC card from The Palantir Corporation?



JNA maps Java boolean to -1 integer?


Is Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?What is the difference between public, protected, package-private and private in Java?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?How do I determine whether an array contains a particular value in Java?How do I convert a String to an int in Java?Creating a memory leak with Java






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








9















I am getting a suprising warning from the native library I am using when passing a boolean value in a JNA structure:



value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE


In this library VK_TRUE and VK_FALSE are #defined as 1 and 0 respectively.



The structure itself isn't particularly complex and everything else appears to be working (the native library seems to treat the 'undefined' boolean as false), but here it is anyway:



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;



If the clipped field is false there is no warning, if it's true then I get the warning - it appears JNA is mapping true to integer -1?



There are not many native boolean values used by this library but I get the same behaviour whenever one is set to true (and again everything else works fine).



In particular, if I change clipped to be an int and set the value explicitly to 1 or 0 everything works!



Is -1 the default value for JNA boolean true?



If so, how would I go about over-riding the type mapping?



Or should I just use int 'manually'?










share|improve this question
























  • Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

    – Steve
    Mar 18 at 17:42











  • Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

    – Steve
    Mar 18 at 17:46












  • @Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

    – stridecolossus
    Mar 19 at 8:07

















9















I am getting a suprising warning from the native library I am using when passing a boolean value in a JNA structure:



value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE


In this library VK_TRUE and VK_FALSE are #defined as 1 and 0 respectively.



The structure itself isn't particularly complex and everything else appears to be working (the native library seems to treat the 'undefined' boolean as false), but here it is anyway:



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;



If the clipped field is false there is no warning, if it's true then I get the warning - it appears JNA is mapping true to integer -1?



There are not many native boolean values used by this library but I get the same behaviour whenever one is set to true (and again everything else works fine).



In particular, if I change clipped to be an int and set the value explicitly to 1 or 0 everything works!



Is -1 the default value for JNA boolean true?



If so, how would I go about over-riding the type mapping?



Or should I just use int 'manually'?










share|improve this question
























  • Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

    – Steve
    Mar 18 at 17:42











  • Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

    – Steve
    Mar 18 at 17:46












  • @Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

    – stridecolossus
    Mar 19 at 8:07













9












9








9








I am getting a suprising warning from the native library I am using when passing a boolean value in a JNA structure:



value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE


In this library VK_TRUE and VK_FALSE are #defined as 1 and 0 respectively.



The structure itself isn't particularly complex and everything else appears to be working (the native library seems to treat the 'undefined' boolean as false), but here it is anyway:



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;



If the clipped field is false there is no warning, if it's true then I get the warning - it appears JNA is mapping true to integer -1?



There are not many native boolean values used by this library but I get the same behaviour whenever one is set to true (and again everything else works fine).



In particular, if I change clipped to be an int and set the value explicitly to 1 or 0 everything works!



Is -1 the default value for JNA boolean true?



If so, how would I go about over-riding the type mapping?



Or should I just use int 'manually'?










share|improve this question
















I am getting a suprising warning from the native library I am using when passing a boolean value in a JNA structure:



value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE


In this library VK_TRUE and VK_FALSE are #defined as 1 and 0 respectively.



The structure itself isn't particularly complex and everything else appears to be working (the native library seems to treat the 'undefined' boolean as false), but here it is anyway:



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;



If the clipped field is false there is no warning, if it's true then I get the warning - it appears JNA is mapping true to integer -1?



There are not many native boolean values used by this library but I get the same behaviour whenever one is set to true (and again everything else works fine).



In particular, if I change clipped to be an int and set the value explicitly to 1 or 0 everything works!



Is -1 the default value for JNA boolean true?



If so, how would I go about over-riding the type mapping?



Or should I just use int 'manually'?







java jna






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 18 at 17:14







stridecolossus

















asked Mar 18 at 16:27









stridecolossusstridecolossus

355213




355213












  • Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

    – Steve
    Mar 18 at 17:42











  • Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

    – Steve
    Mar 18 at 17:46












  • @Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

    – stridecolossus
    Mar 19 at 8:07

















  • Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

    – Steve
    Mar 18 at 17:42











  • Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

    – Steve
    Mar 18 at 17:46












  • @Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

    – stridecolossus
    Mar 19 at 8:07
















Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

– Steve
Mar 18 at 17:42





Something smells fishy here. I would think that correct code would have the actual bit pattern of a boolean field never enter into the equation. A boolean value has two potential states...'true' and 'false'...period. So what is going on where the mapping is being made between boolean and integer values? Does that structure somehow actually contain a malformed bit pattern for 'true', or is something else converting the value to an int and then another something else is expecting a different integer representation?

– Steve
Mar 18 at 17:42













Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

– Steve
Mar 18 at 17:46






Given the constant definitions, is the code expecting that field to be an integer value? Maybe it just needs to be an int. what native library is defining VK_TRUE? - Could this be a function of whatever database definition is persisting this structure?

– Steve
Mar 18 at 17:46














@Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

– stridecolossus
Mar 19 at 8:07





@Steve No databases, JNA is used to invoke native libraries (Without having to go through the JNI hell that it entails).

– stridecolossus
Mar 19 at 8:07












2 Answers
2






active

oldest

votes


















5














JNA maps to native libraries via libffi. There is no bool type in libffi so other mappings must be used -- JNA's default type mapping chooses to map boolean to ffi_type_uint32. This works in the structure(s) because it happens to match the 32-bit mapping size, but not the definition: in C, 0 is false and anything nonzero is true. Only if the native type is also boolean does this 0/non-zero interpretation regain meaning as false/true.



A web search using FFI or JNI and boolean keywords can uncover multiple examples such as this one and this one where unpredictable results occur when libraries are accessed via FFI or JNI and do not conform to the 0 / 1 requirement for boolean values. The latter example appears very similar to this case where a true Java boolean is interpreted as a C int with a value other than 1.



Somewhere under the hood between FFI and your library, and possibly in compiled byte code and/or platform/compiler-dependent type conversions, it's likely that a bitwise "not" is being applied to 0x00000000, turning it into 0xffffffff which is still 'true' in C.



The bottom line is that JNA will by default map Java boolean false to a 32-bit native value of 0, and a Java boolean true to a 32-bit native value that is not 0, and that's all that can be assumed. If your library requires true to have an integer value of 1, either use an integer type that you can specifically set, or use a custom Type Mapping for boolean that sets an int to 0 or 1 for you. JNA's W32APITypeMapper has an example of this conversion to 1 or 0 for the Windows BOOL type.



In your case, assuming you are mapping the VkSwapchainCreateInfoKHR structure defined here, the type of clipped is 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;


Where...



typedef uint32_t VkBool32;


So int is the correct mapping here -- you need to map clipped to a 32-bit integer Edit: As you've pointed out in your answer, it is simple to add your own type mapper to better handle these int values!



(While I'm reviewing the type mappings, you might find IntByReference a better mapping than Pointer for the pQueueFamilyIndices field.) (Your mapping is correct for a variable length int array.)






share|improve this answer




















  • 1





    I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

    – stridecolossus
    Mar 19 at 8:13












  • Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

    – stridecolossus
    Mar 19 at 8:15












  • Ah, you are correct that Pointer is better for a non-fixed length array.

    – Daniel Widdis
    Mar 19 at 13:24


















2














Actually as it turns out there are a lot of booleans in the various native library structures, several hundred of them in fact! It would be nice to preserve the intention of the boolean fields, rather than replacing them all with int just because the implementation enforces that restriction. So I spent some time looking into JNA type conversion...



JNA supports mapping of custom types using a TypeMapper passed as an additional argument to Native::load when the native library is created. Custom type mappings are defined using the Java-to/from-native converter interface TypeConverter.



Defining a custom boolean wrapper that maps Java boolean to/from a C int with 1=true and 0=false is fairly straight-forward:



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;




The type mapper(s) are registered thus:



final DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(VulkanBoolean.class, VulkanBoolean.MAPPER);
...

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.load("vulkan-1", VulkanLibrary.class, options);



However this only works if the structure(s) in question is defined inside the JNA library interface - trivial if one is writing a small library with a handful of structures (which is usually the case) but a bit of a headache when you have several hundred methods and ~500 structures (that are code-generated).



Alternatively the type mapper can be specified in the structure constructor but this requires:



  1. instrumenting every structure that needs the custom mapping(s).


  2. every custom type has to additionally implement NativeMapped so that JNA can determine the native size of the custom type (no idea why essentially the same information has to be specified twice).


  3. each custom type must support a default constructor.


Neither of these are particularly pleasant options, it would nice if JNA supported global type mappings that covered both cases. Guess I need to re code-generate all the structures with the type-mapper. Sigh.



However this only works if the structure(s) in question are defined inside the JNA library interface. A simple workaround is to define a base-class structure within the library and extend all the others from that:



public interface Library 
abstract class VulkanStructure extends Structure
protected VulkanStructure()
super(VulkanLibrary.TYPE_MAPPER);


...


public class VkSwapchainCreateInfoKHR extends VulkanStructure ...


I have used the same mechanism to auto-magically map the ~300 code-generated enumerations to native int that currently look like this:



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;




Currently all structures that refer to an 'enumeration' are actually implemented as an int. With a custom type converter for IntegerEnumeration in place the field type can be the actual Java enumeration and JNA will handle the conversion to/from the integer value (which I currently have to by-hand). This obviously makes the structures slightly more type-safe, definitely clearer, and explicitly refers to the actual enumeration rather than an int - nice.



i.e.



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;
...



(recently found an example doing exactly that here).



Hopefully all this waffling helps someone trying to get their head around the vagaries of JNA.






share|improve this answer

























  • Nice solution! I may steal your enum idea elsewhere.

    – Daniel Widdis
    Mar 19 at 13:27











  • Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

    – Daniel Widdis
    Mar 19 at 23:10






  • 1





    @DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

    – stridecolossus
    Mar 21 at 11:18











  • Excellent! I look forward to looking at it!

    – Daniel Widdis
    Mar 21 at 15:45











  • github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

    – stridecolossus
    Apr 2 at 13:03











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55225896%2fjna-maps-java-boolean-to-1-integer%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









5














JNA maps to native libraries via libffi. There is no bool type in libffi so other mappings must be used -- JNA's default type mapping chooses to map boolean to ffi_type_uint32. This works in the structure(s) because it happens to match the 32-bit mapping size, but not the definition: in C, 0 is false and anything nonzero is true. Only if the native type is also boolean does this 0/non-zero interpretation regain meaning as false/true.



A web search using FFI or JNI and boolean keywords can uncover multiple examples such as this one and this one where unpredictable results occur when libraries are accessed via FFI or JNI and do not conform to the 0 / 1 requirement for boolean values. The latter example appears very similar to this case where a true Java boolean is interpreted as a C int with a value other than 1.



Somewhere under the hood between FFI and your library, and possibly in compiled byte code and/or platform/compiler-dependent type conversions, it's likely that a bitwise "not" is being applied to 0x00000000, turning it into 0xffffffff which is still 'true' in C.



The bottom line is that JNA will by default map Java boolean false to a 32-bit native value of 0, and a Java boolean true to a 32-bit native value that is not 0, and that's all that can be assumed. If your library requires true to have an integer value of 1, either use an integer type that you can specifically set, or use a custom Type Mapping for boolean that sets an int to 0 or 1 for you. JNA's W32APITypeMapper has an example of this conversion to 1 or 0 for the Windows BOOL type.



In your case, assuming you are mapping the VkSwapchainCreateInfoKHR structure defined here, the type of clipped is 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;


Where...



typedef uint32_t VkBool32;


So int is the correct mapping here -- you need to map clipped to a 32-bit integer Edit: As you've pointed out in your answer, it is simple to add your own type mapper to better handle these int values!



(While I'm reviewing the type mappings, you might find IntByReference a better mapping than Pointer for the pQueueFamilyIndices field.) (Your mapping is correct for a variable length int array.)






share|improve this answer




















  • 1





    I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

    – stridecolossus
    Mar 19 at 8:13












  • Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

    – stridecolossus
    Mar 19 at 8:15












  • Ah, you are correct that Pointer is better for a non-fixed length array.

    – Daniel Widdis
    Mar 19 at 13:24















5














JNA maps to native libraries via libffi. There is no bool type in libffi so other mappings must be used -- JNA's default type mapping chooses to map boolean to ffi_type_uint32. This works in the structure(s) because it happens to match the 32-bit mapping size, but not the definition: in C, 0 is false and anything nonzero is true. Only if the native type is also boolean does this 0/non-zero interpretation regain meaning as false/true.



A web search using FFI or JNI and boolean keywords can uncover multiple examples such as this one and this one where unpredictable results occur when libraries are accessed via FFI or JNI and do not conform to the 0 / 1 requirement for boolean values. The latter example appears very similar to this case where a true Java boolean is interpreted as a C int with a value other than 1.



Somewhere under the hood between FFI and your library, and possibly in compiled byte code and/or platform/compiler-dependent type conversions, it's likely that a bitwise "not" is being applied to 0x00000000, turning it into 0xffffffff which is still 'true' in C.



The bottom line is that JNA will by default map Java boolean false to a 32-bit native value of 0, and a Java boolean true to a 32-bit native value that is not 0, and that's all that can be assumed. If your library requires true to have an integer value of 1, either use an integer type that you can specifically set, or use a custom Type Mapping for boolean that sets an int to 0 or 1 for you. JNA's W32APITypeMapper has an example of this conversion to 1 or 0 for the Windows BOOL type.



In your case, assuming you are mapping the VkSwapchainCreateInfoKHR structure defined here, the type of clipped is 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;


Where...



typedef uint32_t VkBool32;


So int is the correct mapping here -- you need to map clipped to a 32-bit integer Edit: As you've pointed out in your answer, it is simple to add your own type mapper to better handle these int values!



(While I'm reviewing the type mappings, you might find IntByReference a better mapping than Pointer for the pQueueFamilyIndices field.) (Your mapping is correct for a variable length int array.)






share|improve this answer




















  • 1





    I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

    – stridecolossus
    Mar 19 at 8:13












  • Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

    – stridecolossus
    Mar 19 at 8:15












  • Ah, you are correct that Pointer is better for a non-fixed length array.

    – Daniel Widdis
    Mar 19 at 13:24













5












5








5







JNA maps to native libraries via libffi. There is no bool type in libffi so other mappings must be used -- JNA's default type mapping chooses to map boolean to ffi_type_uint32. This works in the structure(s) because it happens to match the 32-bit mapping size, but not the definition: in C, 0 is false and anything nonzero is true. Only if the native type is also boolean does this 0/non-zero interpretation regain meaning as false/true.



A web search using FFI or JNI and boolean keywords can uncover multiple examples such as this one and this one where unpredictable results occur when libraries are accessed via FFI or JNI and do not conform to the 0 / 1 requirement for boolean values. The latter example appears very similar to this case where a true Java boolean is interpreted as a C int with a value other than 1.



Somewhere under the hood between FFI and your library, and possibly in compiled byte code and/or platform/compiler-dependent type conversions, it's likely that a bitwise "not" is being applied to 0x00000000, turning it into 0xffffffff which is still 'true' in C.



The bottom line is that JNA will by default map Java boolean false to a 32-bit native value of 0, and a Java boolean true to a 32-bit native value that is not 0, and that's all that can be assumed. If your library requires true to have an integer value of 1, either use an integer type that you can specifically set, or use a custom Type Mapping for boolean that sets an int to 0 or 1 for you. JNA's W32APITypeMapper has an example of this conversion to 1 or 0 for the Windows BOOL type.



In your case, assuming you are mapping the VkSwapchainCreateInfoKHR structure defined here, the type of clipped is 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;


Where...



typedef uint32_t VkBool32;


So int is the correct mapping here -- you need to map clipped to a 32-bit integer Edit: As you've pointed out in your answer, it is simple to add your own type mapper to better handle these int values!



(While I'm reviewing the type mappings, you might find IntByReference a better mapping than Pointer for the pQueueFamilyIndices field.) (Your mapping is correct for a variable length int array.)






share|improve this answer















JNA maps to native libraries via libffi. There is no bool type in libffi so other mappings must be used -- JNA's default type mapping chooses to map boolean to ffi_type_uint32. This works in the structure(s) because it happens to match the 32-bit mapping size, but not the definition: in C, 0 is false and anything nonzero is true. Only if the native type is also boolean does this 0/non-zero interpretation regain meaning as false/true.



A web search using FFI or JNI and boolean keywords can uncover multiple examples such as this one and this one where unpredictable results occur when libraries are accessed via FFI or JNI and do not conform to the 0 / 1 requirement for boolean values. The latter example appears very similar to this case where a true Java boolean is interpreted as a C int with a value other than 1.



Somewhere under the hood between FFI and your library, and possibly in compiled byte code and/or platform/compiler-dependent type conversions, it's likely that a bitwise "not" is being applied to 0x00000000, turning it into 0xffffffff which is still 'true' in C.



The bottom line is that JNA will by default map Java boolean false to a 32-bit native value of 0, and a Java boolean true to a 32-bit native value that is not 0, and that's all that can be assumed. If your library requires true to have an integer value of 1, either use an integer type that you can specifically set, or use a custom Type Mapping for boolean that sets an int to 0 or 1 for you. JNA's W32APITypeMapper has an example of this conversion to 1 or 0 for the Windows BOOL type.



In your case, assuming you are mapping the VkSwapchainCreateInfoKHR structure defined here, the type of clipped is 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;


Where...



typedef uint32_t VkBool32;


So int is the correct mapping here -- you need to map clipped to a 32-bit integer Edit: As you've pointed out in your answer, it is simple to add your own type mapper to better handle these int values!



(While I'm reviewing the type mappings, you might find IntByReference a better mapping than Pointer for the pQueueFamilyIndices field.) (Your mapping is correct for a variable length int array.)







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 23 at 5:31

























answered Mar 18 at 17:56









Daniel WiddisDaniel Widdis

2,13421525




2,13421525







  • 1





    I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

    – stridecolossus
    Mar 19 at 8:13












  • Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

    – stridecolossus
    Mar 19 at 8:15












  • Ah, you are correct that Pointer is better for a non-fixed length array.

    – Daniel Widdis
    Mar 19 at 13:24












  • 1





    I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

    – stridecolossus
    Mar 19 at 8:13












  • Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

    – stridecolossus
    Mar 19 at 8:15












  • Ah, you are correct that Pointer is better for a non-fixed length array.

    – Daniel Widdis
    Mar 19 at 13:24







1




1





I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

– stridecolossus
Mar 19 at 8:13






I feared that might be the case. The structure was code-generated from the C header where (as you point out) VkBool32 -> int, but I intentionally over-rode the mapping to VkBool32 -> Java boolean, hoping that JNA would then map the booleans the 0/1, or at least there was some way to override the resultant mapping, but such is life! As I said it's not a big deal (there aren't that many boolean values), I posted the question mainly for background interest.

– stridecolossus
Mar 19 at 8:13














Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

– stridecolossus
Mar 19 at 8:15






Your aside about the pQueueFamilyIndices is interesting - it's currently a Pointer because the indices is a Java int[], i thought that the various by-reference types were only for parameters returning values using the C reference operator?

– stridecolossus
Mar 19 at 8:15














Ah, you are correct that Pointer is better for a non-fixed length array.

– Daniel Widdis
Mar 19 at 13:24





Ah, you are correct that Pointer is better for a non-fixed length array.

– Daniel Widdis
Mar 19 at 13:24













2














Actually as it turns out there are a lot of booleans in the various native library structures, several hundred of them in fact! It would be nice to preserve the intention of the boolean fields, rather than replacing them all with int just because the implementation enforces that restriction. So I spent some time looking into JNA type conversion...



JNA supports mapping of custom types using a TypeMapper passed as an additional argument to Native::load when the native library is created. Custom type mappings are defined using the Java-to/from-native converter interface TypeConverter.



Defining a custom boolean wrapper that maps Java boolean to/from a C int with 1=true and 0=false is fairly straight-forward:



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;




The type mapper(s) are registered thus:



final DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(VulkanBoolean.class, VulkanBoolean.MAPPER);
...

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.load("vulkan-1", VulkanLibrary.class, options);



However this only works if the structure(s) in question is defined inside the JNA library interface - trivial if one is writing a small library with a handful of structures (which is usually the case) but a bit of a headache when you have several hundred methods and ~500 structures (that are code-generated).



Alternatively the type mapper can be specified in the structure constructor but this requires:



  1. instrumenting every structure that needs the custom mapping(s).


  2. every custom type has to additionally implement NativeMapped so that JNA can determine the native size of the custom type (no idea why essentially the same information has to be specified twice).


  3. each custom type must support a default constructor.


Neither of these are particularly pleasant options, it would nice if JNA supported global type mappings that covered both cases. Guess I need to re code-generate all the structures with the type-mapper. Sigh.



However this only works if the structure(s) in question are defined inside the JNA library interface. A simple workaround is to define a base-class structure within the library and extend all the others from that:



public interface Library 
abstract class VulkanStructure extends Structure
protected VulkanStructure()
super(VulkanLibrary.TYPE_MAPPER);


...


public class VkSwapchainCreateInfoKHR extends VulkanStructure ...


I have used the same mechanism to auto-magically map the ~300 code-generated enumerations to native int that currently look like this:



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;




Currently all structures that refer to an 'enumeration' are actually implemented as an int. With a custom type converter for IntegerEnumeration in place the field type can be the actual Java enumeration and JNA will handle the conversion to/from the integer value (which I currently have to by-hand). This obviously makes the structures slightly more type-safe, definitely clearer, and explicitly refers to the actual enumeration rather than an int - nice.



i.e.



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;
...



(recently found an example doing exactly that here).



Hopefully all this waffling helps someone trying to get their head around the vagaries of JNA.






share|improve this answer

























  • Nice solution! I may steal your enum idea elsewhere.

    – Daniel Widdis
    Mar 19 at 13:27











  • Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

    – Daniel Widdis
    Mar 19 at 23:10






  • 1





    @DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

    – stridecolossus
    Mar 21 at 11:18











  • Excellent! I look forward to looking at it!

    – Daniel Widdis
    Mar 21 at 15:45











  • github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

    – stridecolossus
    Apr 2 at 13:03















2














Actually as it turns out there are a lot of booleans in the various native library structures, several hundred of them in fact! It would be nice to preserve the intention of the boolean fields, rather than replacing them all with int just because the implementation enforces that restriction. So I spent some time looking into JNA type conversion...



JNA supports mapping of custom types using a TypeMapper passed as an additional argument to Native::load when the native library is created. Custom type mappings are defined using the Java-to/from-native converter interface TypeConverter.



Defining a custom boolean wrapper that maps Java boolean to/from a C int with 1=true and 0=false is fairly straight-forward:



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;




The type mapper(s) are registered thus:



final DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(VulkanBoolean.class, VulkanBoolean.MAPPER);
...

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.load("vulkan-1", VulkanLibrary.class, options);



However this only works if the structure(s) in question is defined inside the JNA library interface - trivial if one is writing a small library with a handful of structures (which is usually the case) but a bit of a headache when you have several hundred methods and ~500 structures (that are code-generated).



Alternatively the type mapper can be specified in the structure constructor but this requires:



  1. instrumenting every structure that needs the custom mapping(s).


  2. every custom type has to additionally implement NativeMapped so that JNA can determine the native size of the custom type (no idea why essentially the same information has to be specified twice).


  3. each custom type must support a default constructor.


Neither of these are particularly pleasant options, it would nice if JNA supported global type mappings that covered both cases. Guess I need to re code-generate all the structures with the type-mapper. Sigh.



However this only works if the structure(s) in question are defined inside the JNA library interface. A simple workaround is to define a base-class structure within the library and extend all the others from that:



public interface Library 
abstract class VulkanStructure extends Structure
protected VulkanStructure()
super(VulkanLibrary.TYPE_MAPPER);


...


public class VkSwapchainCreateInfoKHR extends VulkanStructure ...


I have used the same mechanism to auto-magically map the ~300 code-generated enumerations to native int that currently look like this:



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;




Currently all structures that refer to an 'enumeration' are actually implemented as an int. With a custom type converter for IntegerEnumeration in place the field type can be the actual Java enumeration and JNA will handle the conversion to/from the integer value (which I currently have to by-hand). This obviously makes the structures slightly more type-safe, definitely clearer, and explicitly refers to the actual enumeration rather than an int - nice.



i.e.



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;
...



(recently found an example doing exactly that here).



Hopefully all this waffling helps someone trying to get their head around the vagaries of JNA.






share|improve this answer

























  • Nice solution! I may steal your enum idea elsewhere.

    – Daniel Widdis
    Mar 19 at 13:27











  • Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

    – Daniel Widdis
    Mar 19 at 23:10






  • 1





    @DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

    – stridecolossus
    Mar 21 at 11:18











  • Excellent! I look forward to looking at it!

    – Daniel Widdis
    Mar 21 at 15:45











  • github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

    – stridecolossus
    Apr 2 at 13:03













2












2








2







Actually as it turns out there are a lot of booleans in the various native library structures, several hundred of them in fact! It would be nice to preserve the intention of the boolean fields, rather than replacing them all with int just because the implementation enforces that restriction. So I spent some time looking into JNA type conversion...



JNA supports mapping of custom types using a TypeMapper passed as an additional argument to Native::load when the native library is created. Custom type mappings are defined using the Java-to/from-native converter interface TypeConverter.



Defining a custom boolean wrapper that maps Java boolean to/from a C int with 1=true and 0=false is fairly straight-forward:



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;




The type mapper(s) are registered thus:



final DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(VulkanBoolean.class, VulkanBoolean.MAPPER);
...

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.load("vulkan-1", VulkanLibrary.class, options);



However this only works if the structure(s) in question is defined inside the JNA library interface - trivial if one is writing a small library with a handful of structures (which is usually the case) but a bit of a headache when you have several hundred methods and ~500 structures (that are code-generated).



Alternatively the type mapper can be specified in the structure constructor but this requires:



  1. instrumenting every structure that needs the custom mapping(s).


  2. every custom type has to additionally implement NativeMapped so that JNA can determine the native size of the custom type (no idea why essentially the same information has to be specified twice).


  3. each custom type must support a default constructor.


Neither of these are particularly pleasant options, it would nice if JNA supported global type mappings that covered both cases. Guess I need to re code-generate all the structures with the type-mapper. Sigh.



However this only works if the structure(s) in question are defined inside the JNA library interface. A simple workaround is to define a base-class structure within the library and extend all the others from that:



public interface Library 
abstract class VulkanStructure extends Structure
protected VulkanStructure()
super(VulkanLibrary.TYPE_MAPPER);


...


public class VkSwapchainCreateInfoKHR extends VulkanStructure ...


I have used the same mechanism to auto-magically map the ~300 code-generated enumerations to native int that currently look like this:



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;




Currently all structures that refer to an 'enumeration' are actually implemented as an int. With a custom type converter for IntegerEnumeration in place the field type can be the actual Java enumeration and JNA will handle the conversion to/from the integer value (which I currently have to by-hand). This obviously makes the structures slightly more type-safe, definitely clearer, and explicitly refers to the actual enumeration rather than an int - nice.



i.e.



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;
...



(recently found an example doing exactly that here).



Hopefully all this waffling helps someone trying to get their head around the vagaries of JNA.






share|improve this answer















Actually as it turns out there are a lot of booleans in the various native library structures, several hundred of them in fact! It would be nice to preserve the intention of the boolean fields, rather than replacing them all with int just because the implementation enforces that restriction. So I spent some time looking into JNA type conversion...



JNA supports mapping of custom types using a TypeMapper passed as an additional argument to Native::load when the native library is created. Custom type mappings are defined using the Java-to/from-native converter interface TypeConverter.



Defining a custom boolean wrapper that maps Java boolean to/from a C int with 1=true and 0=false is fairly straight-forward:



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;




The type mapper(s) are registered thus:



final DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(VulkanBoolean.class, VulkanBoolean.MAPPER);
...

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.load("vulkan-1", VulkanLibrary.class, options);



However this only works if the structure(s) in question is defined inside the JNA library interface - trivial if one is writing a small library with a handful of structures (which is usually the case) but a bit of a headache when you have several hundred methods and ~500 structures (that are code-generated).



Alternatively the type mapper can be specified in the structure constructor but this requires:



  1. instrumenting every structure that needs the custom mapping(s).


  2. every custom type has to additionally implement NativeMapped so that JNA can determine the native size of the custom type (no idea why essentially the same information has to be specified twice).


  3. each custom type must support a default constructor.


Neither of these are particularly pleasant options, it would nice if JNA supported global type mappings that covered both cases. Guess I need to re code-generate all the structures with the type-mapper. Sigh.



However this only works if the structure(s) in question are defined inside the JNA library interface. A simple workaround is to define a base-class structure within the library and extend all the others from that:



public interface Library 
abstract class VulkanStructure extends Structure
protected VulkanStructure()
super(VulkanLibrary.TYPE_MAPPER);


...


public class VkSwapchainCreateInfoKHR extends VulkanStructure ...


I have used the same mechanism to auto-magically map the ~300 code-generated enumerations to native int that currently look like this:



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;




Currently all structures that refer to an 'enumeration' are actually implemented as an int. With a custom type converter for IntegerEnumeration in place the field type can be the actual Java enumeration and JNA will handle the conversion to/from the integer value (which I currently have to by-hand). This obviously makes the structures slightly more type-safe, definitely clearer, and explicitly refers to the actual enumeration rather than an int - nice.



i.e.



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;
...



(recently found an example doing exactly that here).



Hopefully all this waffling helps someone trying to get their head around the vagaries of JNA.







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 19 at 12:09

























answered Mar 19 at 10:05









stridecolossusstridecolossus

355213




355213












  • Nice solution! I may steal your enum idea elsewhere.

    – Daniel Widdis
    Mar 19 at 13:27











  • Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

    – Daniel Widdis
    Mar 19 at 23:10






  • 1





    @DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

    – stridecolossus
    Mar 21 at 11:18











  • Excellent! I look forward to looking at it!

    – Daniel Widdis
    Mar 21 at 15:45











  • github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

    – stridecolossus
    Apr 2 at 13:03

















  • Nice solution! I may steal your enum idea elsewhere.

    – Daniel Widdis
    Mar 19 at 13:27











  • Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

    – Daniel Widdis
    Mar 19 at 23:10






  • 1





    @DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

    – stridecolossus
    Mar 21 at 11:18











  • Excellent! I look forward to looking at it!

    – Daniel Widdis
    Mar 21 at 15:45











  • github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

    – stridecolossus
    Apr 2 at 13:03
















Nice solution! I may steal your enum idea elsewhere.

– Daniel Widdis
Mar 19 at 13:27





Nice solution! I may steal your enum idea elsewhere.

– Daniel Widdis
Mar 19 at 13:27













Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

– Daniel Widdis
Mar 19 at 23:10





Also I just realized JNA has a built in W32APITypeMapper that already does the conversion to integer 1 / 0.

– Daniel Widdis
Mar 19 at 23:10




1




1





@DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

– stridecolossus
Mar 21 at 11:18





@DanielWiddis - Thought you might like know - this morning I finally achieved the first step of the project I'm working on that has led to the various questions I've posted regarding JNA. A hard-coded triangle rendered using Java and Vulkan! Not much to show for a LOT of effort (several weeks hard slog) but it's definitely a result. Many thanks for the support. At some point I'll update the questions with links to markdown 'blog' I'm planning.

– stridecolossus
Mar 21 at 11:18













Excellent! I look forward to looking at it!

– Daniel Widdis
Mar 21 at 15:45





Excellent! I look forward to looking at it!

– Daniel Widdis
Mar 21 at 15:45













github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

– stridecolossus
Apr 2 at 13:03





github.com/stridecolossus/JOVE/wiki/Technology:-JNA#using-jna

– stridecolossus
Apr 2 at 13:03

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55225896%2fjna-maps-java-boolean-to-1-integer%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해