Search code examples
graalvmgraalvm-native-image

How to represent a C char array in Java with GraalVm


I'm consuming a C library in Java with GraalVm and I have this field (if_name) I don't know how to implement:

# define IFNAMSIZ 16

struct port_t
{
   char if_name[IFNAMSIZ]; 
}

This is my current code:

@CStruct("port_t")
interface Port extends PointerBase {
    
    @CField("if_name")
    WordPointer getIfName();

    @CField("if_name")
    void setIfName(WordPointer ifName);
}

Using WordPointer I get the following error compiling:

Error: Type WordPointer has a size of 8 bytes, but accessed C value has a size of 16 bytes; to suppress this error, use the annotation @AllowNarrowingCast

I already tried with CCharPointer and CCharPointerPointer but those have fixed lengths to 8 bytes and I got a similar error when compiling.

Anyone can help? Thanks in advance


Solution

  • As you already guessed, you'll need to get the address of this field to manipulate it. You can use

    @CStruct("port_t")
    interface Port extends PointerBase {
        @CFieldAddress("if_name")
        CCharPointer addressOfIfName();
    }
    

    In this case it doesn't make sense to have a setter since you cannot change the address of this field. Instead you can use the read/write methods of CCharPointer.

    You'll probably need

    @CConstant
    static native int IFNAMSIZ();
    

    somewhere as well. Then you can do things like

    String foo(Port p, String newIfName) {
        UnsignedWord size = WordFactory.unsigned(IFNAMSIZ());
        String oldIfName = CTypeConversion.toJavaString(p.addressOfIfName(), size);
        CTypeConversion.toCString(newIfName, p.addressOfIfName(), size);
        return oldIfName;
    }