The C struct:
typedef struct {
int32_t tid;
int32_t pos;
uint32_t bin:16, qual:8, l_qname:8;
uint32_t flag:16, n_cigar:16;
int32_t l_qseq;
int32_t mtid;
int32_t mpos;
int32_t isize;
} bam1_core_t;
typedef struct {
bam1_core_t core;
int l_data, m_data;
uint8_t *data;
uint64_t id;
} bam1_t;
The Julia data type I write:
type BinQualLqname
bin::UInt16
qual::UInt8
l_qname::UInt8
end
type FlagNCigar
flag::UInt16
n_cigar::UInt16
end
type Bam1_core_t
tid::Int32
pos::Int32
bin_qual_lqname::BinQualLqname
flag_ncigar::FlagNCigar
l_qseq::Int32
mtid::Int32
mpos::Int32
isize::Int32
end
type Bam1_t
core::Ptr{Bam1_core_t}
l_data::Int32
m_data::Int32
data::Ptr{Cuchar}
id::UInt64
end
When I used above Datatype Bam1_t in julia function:
function sam_read1!(samfile,bamheader,b::Ptr{Bam1_t})
record = ccall((:sam_read1,"libhts"),Cint, (Ptr{Void},Ptr{Void},Ptr{Bam1_t}),samfile,bamheader,b)
end
The data in b modified by sam_read1! is nonsense. How can I debug this? Is there any tools or tips recommended?
sam_read1
int sam_read1(tamFile fp, bam_header_t *header, bam1_t *b);
where
typedef struct {
bam1_core_t core;
int l_aux, data_len, m_data;
uint8_t *data;
} bam1_t;
Seems to be different than your Bam1_t. Would
type Bam1_t
core::Bam1_core_t
l_aux::Int32
data_len::Int32
m_data::Int32
data::Ptr{Cuchar}
end
work?
Related
Payload_Manager.h
typedef struct ATEIS_Payload_s* pATEIS_Payload;
Payload_Manager.c
#include "Payload_Manager.h"
struct __attribute__((__packed__))ATEIS_Payload_s //payload
{
uint32_t Addr;
uint16_t Cmd;
uint16_t Len;
uint8_t Data[];
};
DNM_Manager.h
#include "Payload_Manager.h"
typedef struct DNM_s* pDNM;
pDNM DNMManager_Ctor(pDNM this, pATEIS_Payload src);
DNM_Manager.c
#include "Payload_Manager.h"
struct DNM_s
{
uint32_t Addr;
uint32_t SerialNo;
uint32_t SubnetMask;
uint16_t Tick;
uint8_t Name[NAME_SIZE];
}DNMSet[SET_SIZE], DNMTemp;
pDNM DNMManager_Ctor(pDNM this, pATEIS_Payload src)
{
memcpy(this->Name, &src->Data[NAME], NAME_SIZE); //ptr to incomplete class type is not allowed
this->Addr = src->Addr; //ditto
this->SerialNo = *(uint32_t*)&src->Data[SN]; //ditto
this->SubnetMask = *(uint32_t*)&src->Data[SUBMASK]; //ditto
this->Tick = 0;
return this;
}
main.c
#include "Payload_Manager.h"
#include "DNM_Manager.h"
pDNM DNM_temp = NULL;
DNM_temp = DNMManager_New(); //get one DNM
DNM_temp = DNMManager_Ctor(DNM_temp, pl_p); //init DNM_temp by pl_p
The file DNM_Manager.c needs to know declaration of ATEIS_Payload_s, otherwise it cannot dereference it.
How can I do except that declare ATEIS_Payload_s again in DNM_Manager.c?
Thanks.
As Groo suggested, the implementer must offer functions to user to manipulate members. Here is a snippet from my code:
uint32_t PayloadManager_GetAddr(ATEIS_Payload_s* this)
{
return this->Addr;
}
I have a struct that consists of a union, a variable and a bitfield:
typedef struct router_client {
union {
QHsm *client;
void (*handler)(QSignal sig, QParam par);
};
uint8_t level;
struct {
uint8_t presence:2;
uint8_t is_hsm:1;
uint8_t is_handler:1;
};
} router_client_t;
What is the proper way to initialize it? I used to
router_client_t = {.client=(QHsm*)&qhsm_foo, level = l, \
.presence = p, .is_hsm = s, .is_handler = a}
But when switching toolchain from Code Red MCU tools to Cross GCC I started getting
unknown field 'client' specified in initializer
unknown field 'presence' specified in initializer
...
The point of the union is that I want to be able to assign values either to client or handler and let them share the same pointer.
I tried a few things and I know I can change the struct but I just wanted to know if there is a C99 way of initializing and accessing it.
This can work. I think that the trick is name of structs and union.
typedef union {
int *client;
void (*handler)(int sig, int par);
}union_t;
typedef struct {
uint8_t presence:2;
uint8_t is_hsm:1;
uint8_t is_handler:1;
}struct_t;
typedef struct router_client {
union_t test;
uint8_t level;
struct_t test2
} router_client_t;
void main()
{
int pippo;
router_client_t pippo2= {.test.client=(int*)&pippo, .level = 10, .test2.presence = 2, .test2.is_hsm = 1, .test2.is_handler = 1};
}
Or as you wrote:
#include <stdint.h>
typedef struct router_client {
union{
int *client;
void (*handler)(int sig, int par);
}union_t;
uint8_t level;
struct {
uint8_t presence:2;
uint8_t is_hsm:1;
uint8_t is_handler:1;
}struct_t;
} router_client_t;
void main()
{
int pippo;
router_client_t pippo2= {.union_t.client=(int*)&pippo, .level = 10, .struct_t.presence = 2, .struct_t.is_hsm = 1, .struct_t.is_handler = 1};
}
I see an unnamed struct and an unnamed union.
It is highly probably that the cross gcc compiler is not handling anonymous structs and unions with what ever the default standard is.
suggest adding an appropriate parameter to the compile, something like
'-std=c11'
I'm coding c in IAR Embedded workbench IDE. I have the following in a header file.
typedef union {
uint8_t payload;
struct UBX_NAV_POSLLH nav_posllh;
struct UBX_NAV_STATUS nav_status;
struct UBX_NAV_DOP nav_dop;
struct UBX_NAV_SOL nav_sol;
struct UBX_NAV_VELNED nav_velned;
struct UBX_NAV_TIMEUTC nav_timeutc;
struct UBX_NAV_SVINFO nav_svinfo;
} UBXPayload;
struct UBXHeader {
uint8_t class;
uint8_t id;
uint16_t len;
uint8_t ck_a;
uint8_t ck_b;
};
struct UBXPacket {
struct UBXHeader header;
UBXPayload payload;
};
Here is my source file:
static char *c_buffer
void myinit( )
{
c_buffer= (char*)malloc(50);
}
int myfunc(uint8_t c, char *c_buffer)
{
static uint8_t rx_count = 0;
struct UBXPacket *ubx = (struct UBXPacket *)c_buffer;
for(int i=0; i<3; i++){
ubx->payload.payload[rx_count] = c; /* Error[Pe142]: expression must have pointer- to-object type */
rx_count++;
}
}
void main( )
{
char mychar = 'h';
myinit( );
myfunc(mychar, c_buffer);
}
The same union is defined as follows in another code sample written to be compiled with ARM GCC compiler. It compiles well & works well.
typedef union {
uint8_t payload[0]; /* here [0] is placed */
struct UBX_NAV_POSLLH nav_posllh;
struct UBX_NAV_STATUS nav_status;
struct UBX_NAV_DOP nav_dop;
struct UBX_NAV_SOL nav_sol;
struct UBX_NAV_VELNED nav_velned;
struct UBX_NAV_TIMEUTC nav_timeutc;
struct UBX_NAV_SVINFO nav_svinfo;
} UBXPayload;
But in IAR C compiler giving error. Any suggestions please ?
I do not understand the following line
struct UBXPacket *ubx = (struct UBXPacket *)c_buffer;
In the UBXPayload union the payload member is a single character, but you use it as an array. And when you make it an array you make it an array of size zero so all writes to the array will be out of bounds, leading to undefined behavior (so it's not working so well as you think it does).
I have this structure representing a generic message
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint8_t *data;
} generic_msg_t;
After reading type1 and type 2 I can know to which specific message it corresponds, for example this one:
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint16_t a;
uint8_t b;
uint8_t c;
double d;
double e;
double f;
double g;
double h;
uint8_t i;
} specific_msg_t;
Supposing msg contains verified data, I would like to understand why if I do this I can not access to d, e, f, g, h data (but well a, b, c)
specific_msg_t * specific_msg = (specific_msg_t *) msg;
uint16_t a = specific_msg->a; //OK
double d = specific_msg->d; //NOK`
I have to do instead:
unsigned char * buffer = (unsigned char *) msg;
double d = buffer[15] + (buffer[14] << 8) + (buffer[13] << 16) + (buffer[12] << 24) + (buffer[11] << 32) + (buffer[10] << 40) + (buffer[9] << 48) + (buffer[8] << 56);`
specific_msg_t has potentially different alignment requirements than generic_msg_t so on some architectures, that code could result in a crash - the compiler has no particular requirement to align a generic_msg_t object on a boundary suitable for accessing a double.
It would help to know exactly what error you're getting though.
As long as the sender and receiver use the same headers (uint16_t is the same for both of them) and both of them use the same architecture (e.g. x86 or whatever) there shouldn't be too many problems.
I would also define a union with all the specific message types that you need, in order to avoid those nasty calculations and most of the casts.
Something similar to this:
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
// whatever you need here...
double a;
float b;
// etc.
} specific_msg_t1;
typedef struct {
uint16_t length;
uint8_t type1;
uint8_t type2;
uint16_t a;
uint8_t b;
uint8_t c;
double d;
double e;
double f;
double g;
double h;
uint8_t i;
} specific_msg_t2;
typedef struct
{
uint16_t length;
uint8_t type1;
uint8_t type2;
} selector_msg_t;
typedef union
{
selector_msg_t selector;
specific_msg_t1 msgtype1;
specific_msg_t2 msgtype2;
} message_type_t;
With this setup you could be sending messages of type "message_type_t". Use the member "selector" to decide which specific type of message you received and then use the appropriate specific type to read the different data members.
If the size difference is considerable between the specific types, then it is a bad idea, but if you're not limited by bandwidth then it's at least readable and not that error prone.
Is there a clean way of casting a struct into an uint64_t or any other int, given that struct in <= to the sizeof int?
The only thing I can think of is only an 'ok' solution - to use unions. However I have never been fond of them.
Let me add a code snippet to clarify:
typedef struct {
uint8_t field: 5;
uint8_t field2: 4;
/* and so on... */
}some_struct_t;
some_struct_t some_struct;
//init struct here
uint32_t register;
Now how do i cast some_struct to capture its bits order in uint32_t register.
Hope that makes it a bit clearer.
I've just hit the same problem, and I solved it with a union like this:
typedef union {
struct {
uint8_t field: 5;
uint8_t field2: 4;
/* and so on... */
} fields;
uint32_t bits;
} some_struct_t;
/* cast from uint32_t x */
some_struct_t mystruct = { .bits = x };
/* cast to uint32_t */
uint32_t x = mystruct.bits;
HTH,
Alex
A non-portable solution:
struct smallst {
int a;
char b;
};
void make_uint64_t(struct smallst *ps, uint64_t *pi) {
memcpy(pi, ps, sizeof(struct smallst));
}
You may face problems if you, for example, pack the struct on a little-endian machine and unpack it on a big-endian machine.
you can use pointers and it will be easy
for example:
struct s {
int a:8;
int b:4;
int c:4;
int d:8;
int e:8; }* st;
st->b = 0x8;
st->c = 1;
int *struct_as_int = st;
hope it helps
You can cast object's pointer to desired type and then resolve it. I assume it can be a little bit slower than using unions or something else. But this does not require additional actions and can be used in place.
Short answer:
*(uint16_t *)&my_struct
Example:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint8_t field1;
uint8_t field2;
} MyStruct;
int main() {
MyStruct my_struct = {0xFA, 0x7D};
uint16_t num_my_struct = *(uint16_t *)&my_struct;
printf("%X \n", num_my_struct); // 7DFA
return 0;
}