# Working on spidev.h and spidev.c translation

**URL:** <https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479>\
**Category:** General Usage\
**Created:** [October 16, 2017, 4:42pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479 "2017-10-16T16:42:55Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 4:42pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/1 "2017-10-16T16:42:55Z")

</div>

OK. I have started working on translating spidev.h and spidev.c to Julia. I hope @yuyichao can tell me if I’m heading down the right path on this (I’m trying to somewhat follow what you advises for i2c-dev).

Here’s the C code for the main structure used:

```julia
/**
 * struct spi_ioc_transfer - describes a single SPI transfer
 * @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
 *	If no data is provided, zeroes are shifted out.
 * @rx_buf: Holds pointer to userspace buffer for receive data, or null.
 * @len: Length of tx and rx buffers, in bytes.
 * @speed_hz: Temporary override of the device's bitrate.
 * @bits_per_word: Temporary override of the device's wordsize.
 * @delay_usecs: If nonzero, how long to delay after the last bit transfer
 *	before optionally deselecting the device before the next transfer.
 * @cs_change: True to deselect device before starting the next transfer.
 *
 * This structure is mapped directly to the kernel spi_transfer structure;
 * the fields have the same meanings, except of course that the pointers
 * are in a different address space (and may be of different sizes in some
 * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel).
 * Zero-initialize the structure, including currently unused fields, to
 * accommodate potential future updates.
 *
 * SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync().
 * Pass it an array of related transfers, they'll execute together.
 * Each transfer may be half duplex (either direction) or full duplex.
 *
 *	struct spi_ioc_transfer mesg[4];
 *	...
 *	status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg);
 *
 * So for example one transfer might send a nine bit command (right aligned
 * in a 16-bit word), the next could read a block of 8-bit data before
 * terminating that command by temporarily deselecting the chip; the next
 * could send a different nine bit command (re-selecting the chip), and the
 * last transfer might write some register values.
 */
struct spi_ioc_transfer {
	__u64 tx_buf;
	__u64 rx_buf;

	__u32 len;
	__u32 speed_hz;

	__u16 delay_usecs;
	__u8 bits_per_word;
	__u8 cs_change;
	__u8 tx_nbits;
	__u8 rx_nbits;
	__u16 pad;

	/* If the contents of 'struct spi_ioc_transfer' ever change
	 * incompatibly, then the ioctl number (currently 0) must change;
	 * ioctls with constant size fields get a bit more in the way of
	 * error checking than ones (like this) where that field varies.
	 *
	 * NOTE: struct layout is the same in 64bit and 32bit userspace.
	 */
};

```

I see the largest item as 64-bit - so I created the following (again trying to follow what was done with i2c-dev). I also created some helper functions to get the values out like they would have been used in the C structure.

```julia
struct spi_ioc_transfer 
	block::NTuple{4, UInt64}
end

# ****************************************************************
# The following: get_tx_buf, get_rx_buf, get_len, get_speed,
# get_delay_usecs, get_bits_per_word, get_cs_change,
# get_tx_nbits, get_rx_nbits are helper functions to get the
# proper values out of the block::spi_ioc_transfer structure.
# ****************************************************************
function get_tx_buf(block::spi_ioc_transfer)
	return block[1] #1) 64-bits
end

function get_rx_buf(block::spi_ioc_transfer)
	return block[2] #2) 64-bits
end

function get_len(block::spi_ioc_transfer)
	return block[3] & 0xFFFFFFFF00000000	#3) 32-bits
end

function set_len(len::UInt32)
	num = UInt64(len)
	return num << 32	#needs to be upper
end

function get_speed(block::spi_ioc_transfer)
	return (block[3] << 32) >> 32 #4) 32-bits
end

function get_delay_usecs(block::spi_ioc_transfer)
	return block[4] >> 48 #5) 16-bits
end

function get_bits_per_word(block::spi_ioc_transfer)
	return (block[4] << 16) >> 56 #6) 8-bits	
end

function get_cs_change(block::spi_ioc_transfer)
	return (block[4] << 24) >> 56 #7) 8-bits
end

function get_tx_nbits(block::spi_ioc_transfer)
	return (block[4] << 32) >> 56 #8) 8-bits
end

function get_rx_nbits(block::spi_ioc_transfer)
	return (block[4] << 40) >> 56 #9) 8-bits
end
# ****************************************************************

```

and, here is how it is used in C:

```julia
int spi_xfer(int fd, uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_len){
    struct spi_ioc_transfer spi_message[2];
    memset(spi_message, 0, sizeof(spi_message));
    
    spi_message[0].tx_buf = (unsigned long)tx_buffer;
    spi_message[0].len = tx_len;
    spi_message[1].rx_buf = (unsigned long)rx_buffer;
    spi_message[1].len = rx_len;
    
    return ioctl(fd, SPI_IOC_MESSAGE(2), spi_message);
}

```

And, how I’m trying to use it in Julia. I’m not sure about how to pass an array of structures (or in this case NTuples - if I’m doing this right):

```julia
function spi_xfer(fd::Int32, tx_buffer::UInt8, tx_len::UInt8, rx_buffer::UInt8, rx_len::UInt8)
	tx = spi_ioc_transfer(tx_buffer,0, set_len(tx_len),0)
	rx = spi_ioc_transfer(0,rx_buffer,set_len(rx_len),0)

	spi_message = NTuple{2, spi_ioc_transfer}((rx, tx))
    
    ret = ccall((:ioctl, "libc"), Int, (Cint, Cint, Ref{spi_ioc_transfer}), fd, SPI_IOC_MESSAGE(2), spi_message[1]) 
    return ret
end

```

The link to the spidev.h file has the same contents as what’s on my debian system.

[http://elixir.free-electrons.com/linux/latest/source/include/uapi/linux/spi/spidev.h](http://elixir.free-electrons.com/linux/latest/source/include/uapi/linux/spi/spidev.h)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 16, 2017, 5:52pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/2 "2017-10-16T17:52:36Z")

</div>

> [@Frank\_Applin](#):
>
> I see the largest item as 64-bit - so I created the following (again trying to follow what was done with i2c-dev). I also created some helper functions to get the values out like they would have been used in the C structure.

That advice was only for union, you have a struct here so just declare all the members.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 5:59pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/3 "2017-10-16T17:59:18Z")

</div>

Oh, yeah - right! Thanks.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 6:43pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/4 "2017-10-16T18:43:43Z")

</div>

ok. The structure was simple enough.

```julia
mutable struct spi_ioc_transfer 
	tx_buf::UInt64
	rx_buf::UInt64

	len::UInt32
	speed_hz::UInt32

	delay_usecs::UInt16
	bits_per_word::UInt8
	cs_change::UInt8
	tx_nbits::UInt8
	rx_nbits::UInt8
	pad::UInt16
end

```

Now (as always) - the ccall (and does it need …)?

```julia
function spi_xfer(fd::Int32, tx_buffer::UInt8, tx_len::UInt8, rx_buffer::UInt8, rx_len::UInt8)
	tx = spi_ioc_transfer(tx_buffer, 0, tx_len, 0, 0, 0, 0, 0, 0, 0)
	
	
	rx = spi_ioc_transfer(0, rx_buffer, rx_len, 0, 0, 0, 0, 0, 0, 0)

	spi_message = (tx,rx)
	size = Cint(length(array))

    
    ret = ccall((:ioctl, "libc"), Int, (Cint, Cint, Ptr{spi_message}, size), fd, SPI_IOC_MESSAGE(2), spi_message[1]) 
    return ret
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 16, 2017, 7:25pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/5 "2017-10-16T19:25:06Z")

</div>

Your `ccall` looks strange. `size` shouldn’t be in the signature.

And I think the rule for argument mapping is pretty clear. You should be able to figure out if you need the `...` just by looking at the C declaration of the function.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 7:33pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/6 "2017-10-16T19:33:15Z")

</div>

I think this is it. So, I’ll give it a try (probably tomorrow). I dug up a plot of carrots, yesterday, and now I’m doing KP duty - cutting and cleaning them all.

```julia
ret = ccall((:ioctl, "libc"), Int, (Cint, Cint, Ptr{spi_message}), fd, SPI_IOC_MESSAGE(2), spi_message[1]) 

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 16, 2017, 7:40pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/7 "2017-10-16T19:40:51Z")

</div>

AFAICT the `ioctl` declaration, which you can find in the manpage, is `int ioctl(int fildes, int request, ... /* arg */);` so,

1. Return type is `int` not `long` (It’s the same on 32bit but stil…)

2. The thrid and later arguements are vararg so yes you need the `...`

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 7:53pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/8 "2017-10-16T19:53:35Z")

</div>

Yeah - this is nice:

"No single standard. Arguments, returns, and semantics of ioctl() vary according to the device driver in question (the call is used as a catch-all for operations that don’t cleanly fit the UNIX stream I/O model). "

My manpage didn’t give a type for the return and my Julia (which is 32-bit) gives Int as 32-bit:

```julia
julia> a = Int(1)
1

julia> typeof(a)
Int32

```

So, I assumed just type Int for the return type that it was 32-bit.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 16, 2017, 8:04pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/9 "2017-10-16T20:04:39Z")

</div>

> [@Frank\_Applin](#):
>
> "No single standard. Arguments, returns, and semantics of ioctl() vary according to the device driver in question (the call is used as a catch-all for operations that don’t cleanly fit the UNIX stream I/O model). "

This is describing how the arguments are used, not how they are passed. The way the parameters are passed, which is the only thing `ccall` cares about, is entirely captured in the prototype of the function.

> [@Frank\_Applin](#):
>
> My manpage didn’t give a type for the return

You should report that as a package but at the least. In the mean time you can use [ioctl(2) - Linux manual page](http://man7.org/linux/man-pages/man2/ioctl.2.html)

As I said, `Int` is the same as `Cint` on 32bit, but it is still the wrong one to use to not confuse the reader if anything.

And that link reminds me again that the second parameter is unsigned long on linux so you should use `Clong` or `Culong` instead of `Cint`.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 16, 2017, 8:17pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/10 "2017-10-16T20:17:13Z")

</div>

OK.

```julia
ret = ccall((:ioctl, "libc"), Cint, (Cint, Clong, Ptr{spi_message}...), fd, SPI_IOC_MESSAGE(2), spi_message[1]) 

```

And, thanks, once again for the help.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 18, 2017, 8:48pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/11 "2017-10-18T20:48:26Z")

</div>

OK. I actually have a device attached to my Raspberry Pi where I can start testing the SPI routines. It’s an MCP3008 chip and I’ve tested it with some C++ code and it works great. Now, comes the Julia issues.

The C++ code (the values are from his class):

```julia
enum SPIMODE{
		MODE0 = 0, //!< Low at idle, capture on rising clock edge
		MODE1 = 1, //!< Low at idle, capture on falling clock edge
		MODE2 = 2, //!< High at idle, capture on falling clock edge
		MODE3 = 3 //!< High at idle, capture on rising clock edge
};

SPIMODE mode;
uint8_t bits;
uint32_t speed;
uint16_t delay;

int SPIDevice::setMode(SPIDevice::SPIMODE mode){
	this->mode = mode;
	if (ioctl(this->file, SPI_IOC_WR_MODE, &this->mode)==-1){
		perror("SPI: Can't set SPI mode.");
		return -1;
	}
	if (ioctl(this->file, SPI_IOC_RD_MODE, &this->mode)==-1){
		perror("SPI: Can't get SPI mode.");
		return -1;
	}
	return 0;
}

```

The Julia code:

```julia
type SPIDevice
    bus::UInt8
    device::UInt8
    file::Int
    filename::String
    mode::UInt8
    bits::UInt8
    speed::UInt32
    delay::UInt16
    SPIDevice(bus, device) = new(
                                bus, 
                                device, 
                                0, 
                                "/dev/spidev" * string(bus) * "." * string(device),
                                3,
                                8,
                                488000,
                                0)
end

function spi_setMode(spi::SPIDevice, mode::UInt8)
    spi.mode = mode

    print("1) spi.mode: ")
    println(spi.mode)

     # Set SPI_POL and SPI_PHA 
     ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_WR_MODE, spi.mode) 
     if (ret < 0)
        error("SPI (SPI_IOC_WR_MODE): Can't set SPI mode.")
        return -1
     end

     print("2) spi.mode: ")
     println(spi.mode)
     
     ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_RD_MODE, spi.mode) 
     if (ret < 0)
        error("SPI (SPI_IOC_RD_MODE): Can't get SPI mode.")
         return -1
     end

     print("3) spi.mode: ")
     println(spi.mode)

     return 0
end

```

I’m calling like:

```julia
include("spidev_h.jl")
include("spidev.jl")

import spidev
using spidev

function combineValues(upper::UInt8, lower::UInt8)
    return (Int16(upper) << 8) | Int16(lower)
end

println("Starting RPi SPI ADC Example")

spi = spidev.SPIDevice(0,0)
ret = spidev.spi_open(spi)
ret = spidev.spi_setMode(spi, UInt8(SPI_MODE_0))

```

and here’s the results:

```julia
julia> import spidev

julia> using spidev

julia> function combineValues(upper::UInt8, lower::UInt8)
           return (Int16(upper) << 8) | Int16(lower)
       end
combineValues (generic function with 1 method)

julia> println("Starting RPi SPI ADC Example")
Starting RPi SPI ADC Example

julia> spi = spidev.SPIDevice(0,0)
spidev.SPIDevice(0x00, 0x00, 0, "/dev/spidev0.0", 0x03, 0x08, 0x00077240, 0x0000)

julia> ret = spidev.spi_open(spi)
0

julia> ret = spidev.spi_setMode(spi, UInt8(SPI_MODE_0))
1) spi.mode: 0
2) spi.mode: 0
ERROR: SPI (SPI_IOC_RD_MODE): Can't get SPI mode.
Stacktrace:
 [1] spi_setMode(::spidev.SPIDevice, ::UInt8) at /home/julia-user/julia-0.6.0/bin/spidev.jl:91

```

So, this is telling me it got by the write call OK (SPI\_IOC\_WR\_MODE):

```julia
   spi.mode = mode

    print("1) spi.mode: ")
    println(spi.mode)
     # Set SPI_POL and SPI_PHA 
     ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_WR_MODE, spi.mode) 
     if (ret < 0)
        error("SPI (SPI_IOC_WR_MODE): Can't set SPI mode.")
        return -1
     end

     print("2) spi.mode: ")
     println(spi.mode)

```

and, get’s a -1 back on the read call (SPI\_IOC\_RD\_MODE):

```julia
ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_RD_MODE, spi.mode) 

```

Do you have any ideas?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 19, 2017, 3:14pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/12 "2017-10-19T15:14:08Z")

</div>

Your issue is that `spi.mode` is passed as reference but not as a reference to the field.

I’ve explained this in [Properly using `finalizer`, `ccall`, `cconvert` and `unsafe_convert` - #14 by anon61610682](https://discourse.julialang.org/t/properly-using-finalizer-ccall-cconvert-and-unsafe-convert/6183/14)

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 19, 2017, 5:42pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/13 "2017-10-19T17:42:00Z")

</div>

Well, I had another issue that needed to be fixed by adding in the ioctl.h to this endeavor. I wasn’t get the correct value for SPI\_IOC\_RD\_MODE. Now, I am. I’ll work on the ccall, now.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 19, 2017, 6:00pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/14 "2017-10-19T18:00:22Z")

</div>

I guess I (again) don’t understand. In the C++ code, I am simply passing a variable - yes it’s a field in a structure (not the stucture). So, to test this I changed my C++ code to use simply a variable instead of field member of a structure.

```julia
int SPIDevice::setMode(SPIDevice::SPIMODE mode){
        this->mode = mode;

        if (ioctl(this->file, SPI_IOC_WR_MODE, &mode)==-1){
                perror("SPI: Can't set SPI mode.");
                return -1;
        }
        this->mode = mode;

        if (ioctl(this->file, SPI_IOC_RD_MODE, &mode)==-1){
                perror("SPI: Can't get SPI mode.");
                return -1;
        }
       this->mode = mode;
       return 0;
}

```

This works just fine. So, I’m not understanding why if I do this:

```julia
function spi_setMode(spi::SPIDevice, mode::UInt8)    
       spi.mode = mode

      # Set SPI_POL and SPI_PHA      
      ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_WR_MODE, mode)      
      if (ret < 0)        
           error("SPI (SPI_IOC_WR_MODE): Can't set SPI mode.")        
           return -1     
      end     
      spi.mode = mode

      ret = ccall((:ioctl, "libc"), Int, (Cint, Cuint, Ref{Cuchar}...), spi.file, SPI_IOC_RD_MODE, mode)      
      if (ret < 0)        
          error("SPI (SPI_IOC_RD_MODE): Can't get SPI mode.")         
          return -1     
     end     
     spi.mode = mode

     return 0
end

```

It should work the same way. I’m just passing a variable.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 19, 2017, 6:26pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/15 "2017-10-19T18:26:31Z")

</div>

Using the field isn’t the issue, using a variable has the same effect (except that now the issue is that you are not passing a reference to the variable). See [Properly using `finalizer`, `ccall`, `cconvert` and `unsafe_convert` - #10 by yuyichao](https://discourse.julialang.org/t/properly-using-finalizer-ccall-cconvert-and-unsafe-convert/6183/10) and [Properly using `finalizer`, `ccall`, `cconvert` and `unsafe_convert` - #13 by yuyichao](https://discourse.julialang.org/t/properly-using-finalizer-ccall-cconvert-and-unsafe-convert/6183/13) . I prefer not to repeat that whole thing again but let me know which part is unclear in that explaination…

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 19, 2017, 7:27pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/16 "2017-10-19T19:27:27Z")

</div>

Holy cow - that made things way more confusing. Can we do just a couple simple examples?

Let’s say I have the following struct.

```julia
mutable struct points
    x1::Int32
    y1::Int32
    x2::Int32
    y2::Int32
end

```

So, how would you do a ccall to a library method that wanted 1) the whole struct and 2) just a field of the struct? Let’s say the library is “shapes.so” and the methods are point() and line(). Maybe, the “shapes.so” library adds 1 to each value. I’m sorry if this seems trivial or a waste of time, but some people (like me) learn better from examples.

So, I think the ccall should look like:

```julia
pts = points(10, 12, 14, 16)

x1 = pts.x1
y1 = pts.y1

ccall((:point, "shapes.so"), Int, (Cint, Cint), x1, x2)

ccall((:line, "shapes.so"), Int, (Ref{points}, ), pts)

```

So, can you explain why this simple example is wrong (because I know it is)?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 19, 2017, 7:46pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/17 "2017-10-19T19:46:18Z")

</div>

> [@Frank\_Applin](#):
>
> ccall((:line, “shapes.so”), Int, (Ref{points}, ), pts)

This is actually ok.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 19, 2017, 7:47pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/18 "2017-10-19T19:47:24Z")

</div>

> [@Frank\_Applin](#):
>
> 1. the whole struct and 2) just a field of the struct?

But your library is not taking either of them. Your library is take a reference to a field of a struct.

---

<div class="post-metadata">

**Author:** ![Frank\_Applin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frank_applin/32/1654_2.png) [@Frank\_Applin](https://discourse.julialang.org/u/Frank_Applin)\
**Post date:** [October 19, 2017, 7:53pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/19 "2017-10-19T19:53:16Z")

</div>

> [@Frank\_Applin](#):
>
> ccall((:point, “shapes.so”), Int, (Cint, Cint), x1, x2)

So, does that mean the first one should look like:

```julia
ccall((:point, "shapes.so"), Int, (Ref{Cint}, Ref{Cint}), x1, x2)

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [October 19, 2017, 7:54pm UTC](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479/20 "2017-10-19T19:54:22Z")

</div>

It’s impossible to say since I don’t know and you didn’t say what they want.

[Next page](https://discourse.julialang.org/t/working-on-spidev-h-and-spidev-c-translation/6479.md?page=2)
