How to deliver a struct which contain an array to driverkit by call driverkit function from swift code?

I declare a structure type in swift, name as CmdStruct

struct CmdStruct {
    var cmd:[UInt8]
    init() {
        cmd = [UInt8](repeating: 0, count:16)
    }
}

In the case that the connection has been obtained. In sendCmd function, declare a variable which name as input which type of CmdStruct. After set data to input, call a DriverKit function IOConnectCallStructMethod.

Here xcode shows a warning tip for the parameter 'input' for call IOConnectCallStructMethod:

<Forming 'UnsafeRawPointer' to a variable of type 'CmdStruct'; this is likely incorrect because 'CmdStruct' may contain an object reference.>

func sendCmd() {
    var ret:kern_return_t = kIOReturnSuccess
    var input = cmdStruct()
    var output:[UInt8] = [UInt8](repeating:0, count: 16)
    var inputSize = MemoryLayout<CmdStruct>.size  // print value 8
    var outputSize = output.count // print value 16

    input.cmd[0] = 0x12
    input.cmd[1] = 0x34

    ret = IOConnectCallStructMethod(Connection, selector, &input, inputSize, &output, &outputSize)
}

In C file, driverkit function ExternalMethod will receive the parameter from swift side. And check the value of input->cmd[0] and input->cmd[1] in console. However, the values are not the expected 0x12 and 0x34.

struct CmdStruct
{
    uint8_t cmd[16];
};

kern_return_t myTest::ExternalMethod(uint64_t selector, IOUserClientMethodArguments* arguments, const IOuserClientMethodDispatch* dispatch, OSObject* target, void* reference) 
{
    int i = 0;
    CmdStruct* input = nullptr;

    if (arguments == nullptr) {
        ret = KIOReturnBadArgument;
    }

    if (arguments->structureInput != nullptr) {
        input = (CmdStruct*)arguments->structureInput->getBytestNoCopy();
    }

    /*
    Here to print input->cmd[0] and input->cmd[1] data to console.
    */
}

I expect that the correct value of input will be show on the driverkit side. I'm not sure which part is wrong. Here, I list some factors that may lead to incorrect value.

  1. How to fix the warning tip for parameter 'input' when call IOConnectCallStructMethod in swift.

  2. I get the inputSize value 8 by using MemoryLayout<CmdStruct>.size. But this structure contains a 16 bytes array. How to get the correct struct size in swift

  3. In C file side, using (CmdStruct*)arguments->structureInput->getBytestNoCopy() to transform data to C struct is correct?

If you need to share a structure layout between C and Swift, the only safe way to do that is to define the structure in a C header file and import that into Swift. Swift’s C importer understands C’s layout rules, so your Swift structure will end up with exactly the right layout.

Here xcode shows a warning tip for the parameter

Yep. That’s because cmd is a Swift Array, which is different from a C array [1]. When you import your C CmdStruct type into Swift, you’ll see that Swift imports the cmd member as a large tuple. That presents its own challenges from the Swift side, but at least your C and Swift view of the world will align.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Swift’s array has no direct analogue in C; if you know C++, you can think of it as being like a std::vector.

How to deliver a struct which contain an array to driverkit by call driverkit function from swift code?
 
 
Q