# Losing bytes when reinterpreting

**URL:** https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842
**Category:** General Usage
**Tags:** ccall
**Created:** [March 19, 2024, 9:01pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842 "2024-03-19T21:01:02Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![ion](https://avatars.discourse-cdn.com/v4/letter/i/f1d935/32.png) [@ion](https://discourse.julialang.org/u/ion)
#### Post date: [March 19, 2024, 9:01pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/1 "2024-03-19T21:01:02Z")

</div>

Hi all, I am trying to get data over to C, and I went with a ccall that takes in a buffer from julia. The issue I am having is, the data at teh end of my struct is getting chopped off.

```julia
@kwdef struct CntlOutput
    time_ns::Int64 = 0 
    gyro_valid::Bool = true      
    gyroThetaB_X::Cdouble = 0
    gyroThetaB_Y::Cdouble = 0
    gyroThetaB_Z::Cdouble  

   blah = CntlOutput(56, true, 456, 234, 2364)
   buf = reinterpret(UInt8, [blah])
   ret = ccall((:sendUDPbytes, "./udpSend.so"), Cint, (Ptr{UInt8}, Int64), buf , sizeof(buf ))

```

What I get: _56 1 0.000000 0.000000 0.000000_

Now if I just pass the variables as normal (Int64, Bool, Cdouble, etc) the data comes out just fine. Also, I commented out the bool, and looked at the data, and there was some non-zero data at the end. Does anyone know what is going on here?

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 19, 2024, 9:07pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/2 "2024-03-19T21:07:54Z")

</div>

> [@ion](#):
>
> Hi all, I am trying to get data over to C, and I went with a ccall that takes in a buffer from julia. The issue I am having is, the data at teh end of my struct is getting chopped off.

It’s hard to tell without a runnable example & the function signature on the C side you’re trying to call. Can you provide a fully-formed MWE that others can run on their machine, to help us help you?

> [@ion](#):
>
> Also, I commented out the bool, and looked at the data, and there was some non-zero data at the end. Does anyone know what is going on here?

You’re probably observing padding in the struct. You don’t generally need to `reinterpret` anything when using `ccall`, provided the structs in C & Julia match.

---

<div class="post-metadata">

### Author: ![ion](https://avatars.discourse-cdn.com/v4/letter/i/f1d935/32.png) [@ion](https://discourse.julialang.org/u/ion)
#### Post date: [March 19, 2024, 9:13pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/3 "2024-03-19T21:13:45Z")

</div>

OK, here is the C:

```julia
#include <stdio.h> 
#include <strings.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdbool.h>
#include <string.h>

#define PORT 5000 
#define MAXLINE 1000 

typedef struct {
    int64_t t_imu_gps1980_system_ns; // GPS seconds in the GPS epoch
    bool gyro_valid; // Gyro validity flag
    double x;
    double y;
    double z;

} CntlOutput;
int sendUDPbytes(uint8_t* ptr, uint64_t size) 
{ 
	char buffer[100]; 
	// char *message = "Hello Server";
    // char message[sizeof(CntlOutput)];
    CntlOutput message, messageBuffer;
	memcpy(&messageBuffer, ptr, size);
    message.t_imu_gps1980_system_ns = messageBuffer.t_imu_gps1980_system_ns;
    message.gyro_valid = messageBuffer.gyro_valid;
    message.x = messageBuffer.x;
    message.y = messageBuffer.y;
    message.z = messageBuffer.z;

	char testMessage[size];
	memcpy(&testMessage, ptr, size);
	printf("\r\n");
	for( int i = 0; i < size; i++)
	{
		printf("0x%X",testMessage[i]);
	}
	printf("\r\n");

	// printf("%ld %i %lf %lf %lf\r\n",
	printf("%ld %lf %lf %lf\r\n",
			messageBuffer.t_imu_gps1980_system_ns,
			messageBuffer.gyro_valid,
			messageBuffer.x,
			messageBuffer.y,
			messageBuffer.z

			);

	int sockfd, n; 
	struct sockaddr_in servaddr; 
	(void)n;
	// clear servaddr 
	bzero(&servaddr, sizeof(servaddr)); 
	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
	servaddr.sin_port = htons(PORT); 
	servaddr.sin_family = AF_INET; 
	
	// create datagram socket 
	sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
	
	// connect to server 
	if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) 
	{ 
		printf("\n Error : Connect Failed \n"); 
		exit(0); 
	} 

	// request to send datagram 
	// no need to specify server address in sendto 
	// connect stores the peers IP and port 
	sendto(sockfd, &message, MAXLINE, 0, (struct sockaddr*)NULL, sizeof(servaddr)); 
	
	// waiting for response 
	recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)NULL, NULL); 
	puts(buffer); 

	// close the descriptor 
	close(sockfd);

    return 0;
} 

```

If I don’t reinterpret it it gives me:

> ERROR: LoadError: MethodError: no method matching unsafe\_convert(::Type{Ptr{UInt8}}, ::CntlOutput)

Closest candidates are:  
unsafe\_convert(::Type{Ptr{UInt8}}, ::String)  
@ Base pointer.jl:59  
unsafe\_convert(::Type{Ptr{UInt8}}, ::Symbol)  
@ Base pointer.jl:57  
unsafe\_convert(::Type{Ptr{R}}, ::SubString{String}) where R\<:Union{Int8, UInt8}  
@ Base strings/substring.jl:122  
…

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 19, 2024, 9:29pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/4 "2024-03-19T21:29:02Z")

</div>

Ok, I think I see the issue; there’s a few problems/misconceptions here.

1. Julia structs [match the layout of C structs](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Struct-Type-Correspondences), so there’s no need to go through `uint8_t*`. You can go through `CntlOutput*` just fine, without having to `memcpy` things around.
2. You can then call `sendUDPbytes` by passing a `foo = Ref(blah)` like `@ccall "./udpSend.so".sendUDPbytes(foo::Ptr{CntlOutput}, 1::Cint)`. If your intention is to pass a collection/an array of values to C, you can just pass that too (see [these C wrapper examples](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#C-Wrapper-Examples) from the manual).

> [@ion](#):
>
> If I don’t reinterpret it it gives me:

Yes, because there’s no `cconvert` of the appropriate type defined. See e.g. [Calling C and Fortran Code · The Julia Language](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#automatic-type-conversion)

EDIT: you generally don’t need to define that either, unless you have a fancier wrapper struct that doesn’t match the layout on the C side anymore (e.g. it contains `Array`s where C would have pointers… in those cases, you’ll want to have a “julia version” that you then `cconvert` to a different struct matching the C version).

---

<div class="post-metadata">

### Author: ![ion](https://avatars.discourse-cdn.com/v4/letter/i/f1d935/32.png) [@ion](https://discourse.julialang.org/u/ion)
#### Post date: [March 19, 2024, 9:42pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/5 "2024-03-19T21:42:16Z")

</div>

I changed my function signature to:

```julia
int sendUDPbytes(CntlOutput* ptr)

```

and in Julia:

```julia
ret = ccall((:sendUDPbytes, "./udpSend.so"), Cint, (foo::Ptr{CntlOutput}), blah)

```

Now I get this:

> ERROR: LoadError: syntax: ccall argument types must be a tuple; try “(T,)” around /home/ig/git/julia-test-harness/NetworkComm/cfsPacking.jl:100

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 19, 2024, 9:45pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/6 "2024-03-19T21:45:01Z")

</div>

If you use the `ccall` version, you still need to give it the argument types seperately from the objects themselves. Only the `@ccall` macro can mix them like that. See also their respective docstrings:

[`ccall`](https://docs.julialang.org/en/v1/base/c/#ccall)

> ```julia
> ccall((function_name, library), returntype, (argtype1, ...), argvalue1, ...)
> ccall(function_name, returntype, (argtype1, ...), argvalue1, ...)
> ccall(function_pointer, returntype, (argtype1, ...), argvalue1, ...)
> 
> ```

[`@ccall`](https://docs.julialang.org/en/v1/base/c/#Base.@ccall)

> ```julia
> @ccall library.function_name(argvalue1::argtype1, ...)::returntype
> @ccall function_name(argvalue1::argtype1, ...)::returntype
> @ccall $function_pointer(argvalue1::argtype1, ...)::returntype
> 
> ```

Note that I used `@ccall` (the macro) above, since it makes it easier to figure out which argument will be `cconvert`ed to which type.

---

<div class="post-metadata">

### Author: ![ion](https://avatars.discourse-cdn.com/v4/letter/i/f1d935/32.png) [@ion](https://discourse.julialang.org/u/ion)
#### Post date: [March 19, 2024, 9:49pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/7 "2024-03-19T21:49:08Z")

</div>

```julia
@ccall "./udpSend.so".sendUDPbytes(foo::Ptr{CntlOutput})::Cint

```

This worked!  
Thank you

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [March 19, 2024, 11:09pm UTC](https://discourse.julialang.org/t/losing-bytes-when-reinterpreting/111842/8 "2024-03-19T23:09:55Z")

</div>

> [@ion](#):
>
> `(foo::Ptr{CntlOutput})`

The above is not a tuple. `(foo::Ptr{CntlOutput},)` is a tuple. You need the comma.

```julia-repl
julia> (Ptr{CtrlOutput})
Ptr{CtrlOutput}

julia> (Ptr{CtrlOutput},)
(Ptr{CtrlOutput},)

julia> (Ptr{CtrlOutput}) isa Tuple
false

julia> (Ptr{CtrlOutput},) isa Tuple
true

```
